Compare commits
185 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 901fda9298 | |||
| 7115c0027c | |||
| 7d5aaf6429 | |||
| 79b05cced7 | |||
| 08350a2fde | |||
| 22b1ad7f2f | |||
| bb8bdafddd | |||
| d5e305411f | |||
| 50187b0c65 | |||
| d7908573b8 | |||
| 9aae350c13 | |||
| 390b9770ca | |||
| ba939574a4 | |||
| c50e4a3a06 | |||
| f00f188f0b | |||
| 5a2f45c083 | |||
| 4136806847 | |||
| 6a41458310 | |||
| d70fd34345 | |||
| 3858cc723a | |||
| a6f5b956bf | |||
| 86ecfc84af | |||
| 8cb4fc7221 | |||
| 95d087164d | |||
| 8f3ad0c61d | |||
| 49d42c93ba | |||
| df379b834e | |||
| 3bb004ea2d | |||
| fc478d27c7 | |||
| c690965025 | |||
| 300c9200df | |||
| 4dcef1a835 | |||
| 4519a0b76e | |||
| 3aecdbf0a8 | |||
| dfa8852cfe | |||
| 29fbb4a62b | |||
| de8b02b94d | |||
| dd2f743b3a | |||
| d5dbc12175 | |||
| 643be9738f | |||
| 88b5e492dd | |||
| 810306cb2a | |||
| 43cb8b2460 | |||
| ceb9673330 | |||
| da0b356e3b | |||
| b262ee33c5 | |||
| 12888be4c9 | |||
| 867ac4895b | |||
| a6c9120d06 | |||
| 417901e271 | |||
| 8d1dcef2de | |||
| 30fbd8eb67 | |||
| 76dbd757e3 | |||
| c894c21bf3 | |||
| 008ca7210a | |||
| 60f11dfc0e | |||
| 3aaca28c87 | |||
| d4f0855b19 | |||
| 9d173203ff | |||
| 00c980af68 | |||
| fb9d6e917c | |||
| 2eb0cf28d5 | |||
| 8b054b77b9 | |||
| 4e29ad6898 | |||
| 4ac7a7d01c | |||
| 65efb389c3 | |||
| 83c8f6630c | |||
| 227bfb7419 | |||
| 70eb0397df | |||
| 3c02c6073a | |||
| b3e4d247f0 | |||
| 6aaed94adf | |||
| c3e9c03920 | |||
| 909fa6519d | |||
| 3eea73f07a | |||
| f66c832d56 | |||
| 4de660788d | |||
| 990e280c8f | |||
| af3c8832fe | |||
| 7615e791d3 | |||
| 394ea01d37 | |||
| d19d7b59c8 | |||
| 7dc0a237dc | |||
| 1b4b9cc238 | |||
| 123acec405 | |||
| eaa2ba8faf | |||
| 8b9ac6e5b1 | |||
| 2601e80c8a | |||
| 1b91d8b281 | |||
| db54db3394 | |||
| 84bb6e3a72 | |||
| ce1bc1583b | |||
| 4adf66cb26 | |||
| 8a86351674 | |||
| 418ca6b0a1 | |||
| 73aff4ec69 | |||
| 7ce0926fd9 | |||
| e4ff8ca7d5 | |||
| 5d3981d8b2 | |||
| 3442ca7b62 | |||
| a023a4b090 | |||
| 642f878833 | |||
| 8852cf21cf | |||
| 89f695d6ce | |||
| 975f48f3fa | |||
| 93f6bccaef | |||
| 1a922125bb | |||
| 322aa58fbc | |||
| 4cbf625b84 | |||
| 1b0cddc0ee | |||
| 4f52ff7b9b | |||
| 0cb9b20738 | |||
| 20d5955977 | |||
| ab14747460 | |||
| 6c87889f5c | |||
| c434993763 | |||
| 9fa970a53e | |||
| 87fcf91593 | |||
| 02ddc3889d | |||
| 2fd0248e37 | |||
| b658b8b9de | |||
| 948ac57be6 | |||
| 4802a7a016 | |||
| 244baa4dd4 | |||
| e1f2941d7f | |||
| 98ee6a3983 | |||
| 3f50462ce4 | |||
| 4c5a009305 | |||
| 7e415e636c | |||
| b3bffd6a51 | |||
| cbd6bb984e | |||
| 1aec75d5ad | |||
| 8b631e026c | |||
| 456bc2adb4 | |||
| 8b42254cbb | |||
| 06ccceb810 | |||
| 6ca0461f9b | |||
| 9cbcec63be | |||
| b714c8d170 | |||
| eb807ade7b | |||
| 1f7ce9f88a | |||
| be24a3aa73 | |||
| aaa609b3e2 | |||
| a0e6a3a83d | |||
| 0db498284f | |||
| d8ae606a55 | |||
| e940ad09b4 | |||
| 633f63b104 | |||
| db4b6395ef | |||
| fa1d496cf5 | |||
| 310713da0e | |||
| 3e545f1d50 | |||
| 278fd47e52 | |||
| 26b87e0659 | |||
| 38decd8b58 | |||
| a05b4fe867 | |||
| 7b82b2c2c8 | |||
| 4d5ad0a00c | |||
| c5d5038b4d | |||
| be8161bac1 | |||
| cdd248d116 | |||
| 26d55bc048 | |||
| 218e2125e3 | |||
| 5f1b4fa5f5 | |||
| a40c431396 | |||
| 40a797c0da | |||
| f8a2d646dc | |||
| 224f7a15d0 | |||
| 25024aae6b | |||
| 4ab01f4faf | |||
| 5ae66a0614 | |||
| d38fb078f9 | |||
| f1587af451 | |||
| ddf434f595 | |||
| 22112e47b2 | |||
| 9363bafec4 | |||
| 3d07894b2d | |||
| 262b5a36aa | |||
| 7745fe6e65 | |||
| 189f95cb04 | |||
| f3250ededc | |||
| 9820c5dba7 | |||
| 7b9a473296 | |||
| 23e68c1c4f | |||
| c9414f7f08 |
@@ -25,8 +25,10 @@ jobs:
|
||||
cd doc
|
||||
mkdir technical
|
||||
doxygen musrfit_dox.cfg
|
||||
doxygen musredit_qt5_dox.cfg
|
||||
doxygen mupp_qt5_dox.cfg
|
||||
doxygen musredit_qt6_dox.cfg
|
||||
doxygen mupp_qt6_dox.cfg
|
||||
doxygen musrStep_qt6_dox.cfg
|
||||
doxygen musrWiz_qt6_dox.cfg
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
@@ -40,5 +42,4 @@ jobs:
|
||||
cp -r ./doc/technical/html/* .
|
||||
git add .
|
||||
git commit -m "Deploy site"
|
||||
git push -f https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git gitea-pages
|
||||
|
||||
git push --verbose -f https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git gitea-pages
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
# - musrfit
|
||||
cmake_minimum_required(VERSION 3.17)
|
||||
|
||||
project(musrfit VERSION 1.9.9 LANGUAGES C CXX)
|
||||
# cmake: use BoostConfig.cmake instead of FindBoost
|
||||
if (CMAKE_VERSION GREATER_EQUAL "3.3")
|
||||
cmake_policy(SET CMP0167 NEW)
|
||||
endif ()
|
||||
|
||||
project(musrfit VERSION 1.10.0 LANGUAGES C CXX)
|
||||
|
||||
#--- musrfit specific options -------------------------------------------------
|
||||
option(nexus "build optional NeXus support. Needed for ISIS" OFF)
|
||||
@@ -92,11 +97,19 @@ endif ()
|
||||
set(ROOT_GRTEQ_24 ${ROOT_GRTEQ_24} CACHE INTERNAL "ROOT Version check")
|
||||
|
||||
#--- check for boost ----------------------------------------------------------
|
||||
find_package(Boost REQUIRED
|
||||
COMPONENTS
|
||||
system
|
||||
filesystem
|
||||
)
|
||||
find_package(Boost QUIET)
|
||||
if (Boost_VERSION VERSION_GREATER_EQUAL "1.89")
|
||||
find_package(Boost REQUIRED
|
||||
COMPONENTS
|
||||
filesystem
|
||||
)
|
||||
else (Boost_VERSION VERSION_GREATER_EQUAL "1.89")
|
||||
find_package(Boost REQUIRED
|
||||
COMPONENTS
|
||||
system
|
||||
filesystem
|
||||
)
|
||||
endif (Boost_VERSION VERSION_GREATER_EQUAL "1.89")
|
||||
message(STATUS "Boost libs: ${Boost_LIBRARIES}")
|
||||
|
||||
#--- check for gsl ------------------------------------------------------------
|
||||
@@ -198,13 +211,40 @@ if (qt_based_tools)
|
||||
endif (qt_version STREQUAL 3)
|
||||
endif (qt_based_tools)
|
||||
|
||||
#--- if NeXus check also for HDF4, HDF5, and MXML -----------------------------
|
||||
#--- if NeXus check also for HDF4 (optional), HDF5 ----------------------------
|
||||
if (nexus)
|
||||
find_package(HDF5 COMPONENTS CXX REQUIRED)
|
||||
if (HAVE_HDF4)
|
||||
find_package(HDF4 REQUIRED)
|
||||
#--- check for HDF4 -----------------------------------------------------------
|
||||
# Find HDF4 manually (pkg-config often doesn't have hdf4)
|
||||
find_path(HDF4_INCLUDE_DIR
|
||||
NAMES mfhdf.h
|
||||
PATHS /usr/include /usr/local/include
|
||||
PATH_SUFFIXES hdf
|
||||
)
|
||||
|
||||
find_library(HDF4_DF_LIBRARY
|
||||
NAMES df libdf
|
||||
PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib
|
||||
)
|
||||
|
||||
find_library(HDF4_MFHDF_LIBRARY
|
||||
NAMES mfhdf libmfhdf
|
||||
PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib
|
||||
)
|
||||
|
||||
if (HDF4_INCLUDE_DIR AND HDF4_DF_LIBRARY AND HDF4_MFHDF_LIBRARY)
|
||||
set(HDF4_FOUND TRUE)
|
||||
set(HDF4_INCLUDE_DIRS ${HDF4_INCLUDE_DIR})
|
||||
set(HDF4_LIBRARIES ${HDF4_MFHDF_LIBRARY} ${HDF4_DF_LIBRARY})
|
||||
message(STATUS "Found HDF4: ${HDF4_INCLUDE_DIR}")
|
||||
message(STATUS " HDF4 libraries: ${HDF4_LIBRARIES}")
|
||||
else()
|
||||
message(FATAL_ERROR "HDF4 library not found. Please install libhdf4-dev or hdf-devel")
|
||||
endif()
|
||||
|
||||
add_definitions(-DHAVE_HDF4)
|
||||
endif (HAVE_HDF4)
|
||||
find_package(NEXUS REQUIRED)
|
||||
add_definitions(-DPNEXUS_ENABLED)
|
||||
endif (nexus)
|
||||
|
||||
@@ -226,13 +266,15 @@ endif ()
|
||||
|
||||
#--- start create git-revision.h ----------------------------------------------
|
||||
if (IS_GIT_REPO)
|
||||
execute_process(COMMAND sh ${CMAKE_SOURCE_DIR}/src/git_revision.sh)
|
||||
add_custom_target(git_revision ALL
|
||||
COMMAND sh ${CMAKE_SOURCE_DIR}/src/git_revision.sh ${CMAKE_BINARY_DIR}/src
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMENT "Checking git revision"
|
||||
)
|
||||
|
||||
set(HAVE_GIT_REV_H "-DHAVE_GIT_REV_H")
|
||||
set(GIT_REV_H "git-revision.h")
|
||||
set(HAVE_GIT_REV_H "-DHAVE_GIT_REV_H")
|
||||
else (IS_GIT_REPO)
|
||||
set(HAVE_GIT_REV_H "")
|
||||
set(GIT_REV_H "")
|
||||
set(HAVE_GIT_REV_H "")
|
||||
endif (IS_GIT_REPO)
|
||||
|
||||
#--- end create git-revision.h ------------------------------------------------
|
||||
@@ -263,6 +305,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)
|
||||
|
||||
@@ -307,7 +353,6 @@ if (nexus)
|
||||
message(" HDF4 not present.")
|
||||
endif (HAVE_HDF4)
|
||||
message(" HDF5 found in ${HDF5_INCLUDE_DIRS}, Version: ${HDF5_VERSION}")
|
||||
message(" NeXus found in ${NEXUS_INCLUDE_DIR}, Version: ${NEXUS_VERSION_STRING}")
|
||||
endif (nexus)
|
||||
|
||||
message("")
|
||||
|
||||
16
ChangeLog
16
ChangeLog
@@ -6,11 +6,23 @@ The ChangeLog will describe feature changes rather than coding detail changes.
|
||||
|
||||
For detailed information about changes have a look here:
|
||||
|
||||
https://gitlab.psi.ch/nemu/musrfit/activity
|
||||
https://gitea.psi.ch/LMU/musrfit
|
||||
|
||||
or
|
||||
|
||||
https://bitbucket.org/muonspin/musrfit/commits/all
|
||||
https://bitbucket.org/muonspin/musrfit
|
||||
|
||||
Release of V1.10.0, 2026/02/21
|
||||
==============================
|
||||
|
||||
ditch the use of the NeXus lib. NeXus files are now directly read via hdf4/5
|
||||
add deadtime correction of pulsed sources, assuming the relevant parameters are
|
||||
present in the file.
|
||||
|
||||
Release of V1.9.10, 2026/01/16
|
||||
==============================
|
||||
|
||||
function handling lifted from boost/spirit classic/qi to x3
|
||||
|
||||
Release of V1.9.9, 2025/06/08
|
||||
=============================
|
||||
|
||||
6
INSTALL
6
INSTALL
@@ -18,7 +18,7 @@ directory and
|
||||
cd build
|
||||
cmake ../ -DCMAKE_INSTALL_PREFIX=$ROOTSYS (or where ever musrfit should be installed)
|
||||
cmake --build ./ --clean-first
|
||||
make install (as superuser -- maybe)
|
||||
cmake --install ./ (as superuser -- maybe)
|
||||
/sbin/ldconfig (as superuser)
|
||||
|
||||
cmake configuration allows a couple of switches. For details check the documentation at
|
||||
@@ -31,7 +31,7 @@ An example with NeXus support and BMWlibs needed would look like this
|
||||
cd build
|
||||
cmake ../ -Dnexus=1 -DBMWlibs=1 -DCMAKE_INSTALL_PREFIX=$ROOTSYS
|
||||
cmake --build ./ --clean-first
|
||||
make install (as superuser -- maybe)
|
||||
cmake --install ./ (as superuser -- maybe)
|
||||
/sbin/ldconfig (as superuser)
|
||||
|
||||
In the optimal case everything is ready to be used ;-)
|
||||
@@ -43,7 +43,7 @@ In the optimal case everything is ready to be used ;-)
|
||||
More information regarding software requirements and the installation process
|
||||
can be found here:
|
||||
|
||||
http://lmu.web.psi.ch/musrfit/user/MUSR/MusrFitSetup.html
|
||||
https://lmu.pages.psi.ch/musrfit-docu/setup-standard.html
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# this is the end ...
|
||||
|
||||
2
README
2
README
@@ -32,7 +32,7 @@ Documentation
|
||||
|
||||
For a more exhaustive user documentation see:
|
||||
|
||||
http://lmu.web.psi.ch/musrfit/user/html/index.html
|
||||
https://lmu.pages.psi.ch/musrfit-docu/index.html
|
||||
|
||||
Contacts
|
||||
|
||||
|
||||
74
README.md
74
README.md
@@ -1,37 +1,37 @@
|
||||
# musrfit - muSR and beta-NMR data analysis package #
|
||||
|
||||
### Contents ###
|
||||
|
||||
This is a data analysis package to analyze time differential muSR and beta-NMR data.
|
||||
Currently it allows the following:
|
||||
|
||||
* set up most commonly used fitting functions for muSR and beta-NMR
|
||||
* fit data, including global fits
|
||||
* show the fit results and the residuals
|
||||
* show the Fourier transform of the data
|
||||
* easily extract the fit parameters and import in other programs (gnuplot, qtiplot/origin, ...)
|
||||
* generate input fitting files for follow-up runs
|
||||
* generate global input fitting files based on a single run template
|
||||
* implement more sophisticated user functions
|
||||
(e.g. GL vortex lattice, Meissner screening including low-energy muon stopping profiles)
|
||||
|
||||
### Currently supported platforms: ###
|
||||
|
||||
* Linux
|
||||
* Mac OS X
|
||||
* Windows 10 1809 or newer - current state is for the commited ones
|
||||
* Web based implementation - http://musruser.psi.ch/cgi-bin/musrfit.cgi
|
||||
|
||||
### Documentation ####
|
||||
|
||||
For a more exhaustive user documentation see:
|
||||
|
||||
http://lmu.web.psi.ch/musrfit/user/html/index.html
|
||||
|
||||
### Contacts ###
|
||||
|
||||
<andreas.suter@psi.ch>
|
||||
|
||||
For the beta-NMR related parts, please contact Zaher Salman
|
||||
<zaher.salman@psi.ch>
|
||||
|
||||
# musrfit - muSR and beta-NMR data analysis package #
|
||||
|
||||
### Contents ###
|
||||
|
||||
This is a data analysis package to analyze time differential muSR and beta-NMR data.
|
||||
Currently it allows the following:
|
||||
|
||||
* set up most commonly used fitting functions for muSR and beta-NMR
|
||||
* fit data, including global fits
|
||||
* show the fit results and the residuals
|
||||
* show the Fourier transform of the data
|
||||
* easily extract the fit parameters and import in other programs (gnuplot, qtiplot/origin, ...)
|
||||
* generate input fitting files for follow-up runs
|
||||
* generate global input fitting files based on a single run template
|
||||
* implement more sophisticated user functions
|
||||
(e.g. GL vortex lattice, Meissner screening including low-energy muon stopping profiles)
|
||||
|
||||
### Currently supported platforms: ###
|
||||
|
||||
* Linux
|
||||
* Mac OS X
|
||||
* Windows 10 1809 or newer - current state is for the commited ones
|
||||
* Web based implementation - http://musruser.psi.ch/cgi-bin/musrfit.cgi
|
||||
|
||||
### Documentation ####
|
||||
|
||||
For a more exhaustive user documentation see:
|
||||
|
||||
https://lmu.pages.psi.ch/musrfit-docu/index.html
|
||||
|
||||
### Contacts ###
|
||||
|
||||
<andreas.suter@psi.ch>
|
||||
|
||||
For the beta-NMR related parts, please contact Zaher Salman
|
||||
<zaher.salman@psi.ch>
|
||||
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
## Process this file with cmake
|
||||
#=============================================================================
|
||||
# NeXus - Neutron & X-ray Common Data Format
|
||||
#
|
||||
# CMakeLists for building the NeXus library and applications.
|
||||
#
|
||||
# Copyright (C) 2011 Stephen Rankin
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by the
|
||||
# Free Software Foundation; either version 2 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
# for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# For further information, see <http://www.nexusformat.org>
|
||||
#
|
||||
#
|
||||
#=============================================================================
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# find the runtime binaries of the HDF4 library
|
||||
#------------------------------------------------------------------------------
|
||||
find_library(HDF4_DF_LIBRARY NAMES df hdf
|
||||
HINTS ENV HDF4_ROOT
|
||||
PATH_SUFFIXES hdf)
|
||||
|
||||
|
||||
if(HDF4_DF_LIBRARY MATCHES HDF4_DF_LIBRARY-NOTFOUND)
|
||||
message(FATAL_ERROR "Could not find HDF4 DF library!")
|
||||
else()
|
||||
get_filename_component(HDF4_LIBRARY_DIRS ${HDF4_DF_LIBRARY} PATH)
|
||||
message(STATUS "Found HDF4 DF library: ${HDF4_DF_LIBRARY}")
|
||||
message(STATUS "HDF4 libary path: ${HDF4_LIBRARY_DIRS}")
|
||||
endif()
|
||||
|
||||
find_library(HDF4_MFHDF_LIBRARY NAMES mfhdf
|
||||
HINTS ENV HDF4_ROOT
|
||||
PATH_SUFFIXES hdf)
|
||||
|
||||
if(HDF4_MFHDF_LIBRARY MATCHES HDF4_MFHDF_LIBRARY-NOTFOUND)
|
||||
message(FATAL_ERROR "Could not find HDF5 MFHDF library!")
|
||||
else()
|
||||
message(STATUS "Found HDF4 MFHDF library: ${HDF4_MFHDF_LIBRARY}")
|
||||
endif()
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# find the HDF4 header file
|
||||
#------------------------------------------------------------------------------
|
||||
find_path(HDF4_INCLUDE_DIRS mfhdf.h
|
||||
HINTS ENV HDF4_ROOT
|
||||
PATH_SUFFIXES hdf)
|
||||
|
||||
if(HDF4_INCLUDE_DIRS MATCHES HDF4_INCLUDE_DIRS-NOTFOUND)
|
||||
message(FATAL_ERROR "Could not find HDF4 header files")
|
||||
else()
|
||||
message(STATUS "Found HDF4 header files in: ${HDF4_INCLUDE_DIRS}")
|
||||
endif()
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# search for additional packages required to link against HDF4
|
||||
#------------------------------------------------------------------------------
|
||||
find_package(JPEG REQUIRED)
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# add libraries to the link list for NAPI
|
||||
#------------------------------------------------------------------------------
|
||||
get_filename_component(LIB_EXT ${HDF4_DF_LIBRARY} EXT)
|
||||
if(LIB_EXT MATCHES .a)
|
||||
message(STATUS "HDF4 DF library is static")
|
||||
list(APPEND NAPI_LINK_LIBS "-Wl,-whole-archive" ${HDF4_DF_LIBRARY} "-Wl,-no-whole-archive")
|
||||
else()
|
||||
list(APPEND NAPI_LINK_LIBS ${HDF4_DF_LIBRARY})
|
||||
endif()
|
||||
|
||||
|
||||
get_filename_component(LIB_EXT ${HDF4_MFHDF_LIBRARY} EXT)
|
||||
if(LIB_EXT MATCHES .a)
|
||||
message(STATUS "HDF4 MFHDF library is static")
|
||||
list(APPEND NAPI_LINK_LIBS "-Wl,-whole-archive" ${HDF4_MFHDF_LIBRARY} "-Wl,-no-whole-archive")
|
||||
else()
|
||||
list(APPEND NAPI_LINK_LIBS ${HDF4_MFHDF_LIBRARY})
|
||||
endif()
|
||||
|
||||
list(APPEND NAPI_LINK_LIBS jpeg)
|
||||
|
||||
include_directories ( SYSTEM ${HDF4_INCLUDE_DIRS} )
|
||||
link_directories(${HDF4_LIBRARY_DIRS})
|
||||
@@ -1,34 +0,0 @@
|
||||
# - find MXML
|
||||
# find the MXML lib and includes
|
||||
# This module defines
|
||||
# LIBMXML_INCLUDE_DIR, where to find mxml.h
|
||||
# LIBMXML_LIBRARY, library to link against
|
||||
# LIBMXML_FOUND, if false, do not try to use the MXML lib
|
||||
|
||||
find_path(LIBMXML_INCLUDE_DIR mxml.h
|
||||
HINT "/usr/include"
|
||||
)
|
||||
# find position of mxml.h from the end
|
||||
string(FIND "${LIBMXML_INCLUDE_DIR}" "/mxml.h" pos REVERSE)
|
||||
# truncate the string
|
||||
string(SUBSTRING "${LIBMXML_INCLUDE_DIR}" 0 ${pos} substr)
|
||||
set(LIBMXML_INCLUDE_DIR ${substr})
|
||||
unset(substr)
|
||||
|
||||
find_library(LIBMXML_LIBRARY mxml)
|
||||
|
||||
# get version string
|
||||
# currently do not know from where to get it automatically
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set LIBMXML_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MXML
|
||||
REQUIRED_VARS LIBMXML_LIBRARY LIBMXML_INCLUDE_DIR)
|
||||
|
||||
if (NOT LIBMXML_FOUND)
|
||||
unset(LIBMXML_LIBRARY)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBMXML_INCLUDE_DIR LIBMXML_LIBRARY)
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
# - Find NeXus library
|
||||
# Find the native NEXUS includes and library
|
||||
# This module defines
|
||||
# NEXUS_INCLUDE_DIR, where to find NeXus.h, etc.
|
||||
# NEXUS_LIBRARY, library to link against to use NEXUS
|
||||
# NEXUS_FOUND, if false, do not try to use NEXUS.
|
||||
|
||||
find_path(NEXUS_INCLUDE_DIR napi.h
|
||||
HINTS "/usr/local/include" "/opt/nexus/include" "/usr/local/include/nexus"
|
||||
)
|
||||
# find position of napi.h from the end
|
||||
string(FIND "${NEXUS_INCLUDE_DIR}" "/napi.h" pos REVERSE)
|
||||
# truncate the string
|
||||
string(SUBSTRING "${NEXUS_INCLUDE_DIR}" 0 ${pos} substr)
|
||||
set(NEXUS_INCLUDE_DIR ${substr})
|
||||
unset(substr)
|
||||
|
||||
find_library(NEXUS_LIBRARY NeXus
|
||||
HINTS "/usr/lib" "/usr/lib64" "/usr/local/lib" "/usr/local/lib64" "/opt/nexus/lib")
|
||||
|
||||
# get version string
|
||||
if (NEXUS_INCLUDE_DIR AND EXISTS ${NEXUS_INCLUDE_DIR}/napi.h)
|
||||
file(STRINGS "${NEXUS_INCLUDE_DIR}/napi.h" NEXUS_version_str
|
||||
REGEX "^#define[\t ]+NEXUS_VERSION[\t ].*")
|
||||
|
||||
string(REGEX REPLACE "^#define[\t ]+NEXUS_VERSION[\t ]+\"([^\"]*).*"
|
||||
"\\1" NEXUS_VERSION_STRING "${NEXUS_version_str}")
|
||||
unset(NEXUS_version_str)
|
||||
endif()
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set NEXUS_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(NEXUS
|
||||
REQUIRED_VARS NEXUS_LIBRARY NEXUS_INCLUDE_DIR
|
||||
VERSION_VAR NEXUS_VERSION_STRING)
|
||||
|
||||
if (NOT NEXUS_FOUND)
|
||||
unset(NEXUS_LIBRARY)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(NEXUS_INCLUDE_DIR NEXUS_LIBRARY)
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
Binary file not shown.
BIN
doc/examples/data/emu00139040.nxs
Normal file
BIN
doc/examples/data/emu00139040.nxs
Normal file
Binary file not shown.
BIN
doc/examples/data/lem15_his_2992.root
Normal file
BIN
doc/examples/data/lem15_his_2992.root
Normal file
Binary file not shown.
BIN
doc/examples/data/lem15_his_2993.root
Normal file
BIN
doc/examples/data/lem15_his_2993.root
Normal file
Binary file not shown.
BIN
doc/examples/data/lem15_his_2994.root
Normal file
BIN
doc/examples/data/lem15_his_2994.root
Normal file
Binary file not shown.
@@ -1,34 +1,34 @@
|
||||
nc-ZnO T=80 F=69
|
||||
Ag_T=100_F=20
|
||||
###############################################################
|
||||
FITPARAMETER
|
||||
# No Name Value Step Pos_Error Boundaries
|
||||
1 alpha 0.88008 -0.00063 0.00063
|
||||
2 asym 0.1708 -0.0017 0.0017 0 0.3
|
||||
3 phase 3.90 -0.38 0.38 0 100
|
||||
4 field 71.003 -0.036 0.036 0 none
|
||||
5 rate 0.1526 -0.0024 0.0024 0 100
|
||||
6 beta 1.231 -0.046 0.047
|
||||
1 alpha 1.02344 -0.00095 0.00095
|
||||
2 asym 0.23676 -0.00098 0.00098 0 0.3
|
||||
3 phase 0 0 none 0 100
|
||||
4 field 20.300 -0.010 0.010 0 none
|
||||
5 rate 0.0040 -0.0013 0.0013 0 100
|
||||
|
||||
###############################################################
|
||||
THEORY
|
||||
asymmetry 2
|
||||
TFieldCos 3 fun1 (phase frequency)
|
||||
generExpo 5 6 (rate exponent)
|
||||
simplExpo 5 (rate)
|
||||
|
||||
###############################################################
|
||||
FUNCTIONS
|
||||
fun1 = gamma_mu * par4
|
||||
|
||||
###############################################################
|
||||
RUN data/EMU00005989_v2 EMU ISIS NEXUS (name beamline institute data-file-format)
|
||||
RUN data/emu00139040 EMU ISIS NEXUS (name beamline institute data-file-format)
|
||||
fittype 2 (asymmetry fit)
|
||||
alpha 1
|
||||
map 0 0 0 0 0 0 0 0 0 0
|
||||
forward 1-16
|
||||
backward 17-32
|
||||
forward 1-48
|
||||
backward 49-96
|
||||
backgr.fix 0 0
|
||||
data 40 1500 40 1500
|
||||
fit 0.2 14
|
||||
data 10 2048 10 2048
|
||||
deadtime-cor file
|
||||
fit 0.144 14
|
||||
packing 1
|
||||
|
||||
###############################################################
|
||||
@@ -39,19 +39,19 @@ SAVE
|
||||
|
||||
###############################################################
|
||||
FOURIER
|
||||
units Gauss # units either 'Gauss', 'MHz', or 'Mc/s'
|
||||
units Gauss # units either 'Gauss', 'Tesla', 'MHz', or 'Mc/s'
|
||||
fourier_power 10
|
||||
apodization STRONG # NONE, WEAK, MEDIUM, STRONG
|
||||
plot REAL # REAL, IMAG, REAL_AND_IMAG, POWER, PHASE
|
||||
plot REAL # REAL, IMAG, REAL_AND_IMAG, POWER, PHASE, PHASE_OPT_REAL
|
||||
range 0 100
|
||||
phase par2
|
||||
|
||||
###############################################################
|
||||
PLOT 2 (asymmetry plot)
|
||||
runs 1
|
||||
range 0 14 -0.22 0.22
|
||||
view_packing 5
|
||||
range 0 14 -0.32 0.32
|
||||
view_packing 10
|
||||
|
||||
###############################################################
|
||||
STATISTIC --- 2012-03-20 10:28:41
|
||||
chisq = 796.7, NDF = 846, chisq/NDF = 0.941749
|
||||
STATISTIC --- 2026-02-21 13:10:28
|
||||
chisq = 1166.4, NDF = 863, chisq/NDF = 1.351562
|
||||
|
||||
@@ -1,49 +1,50 @@
|
||||
nc-ZnO T=80 F=69
|
||||
Ag_T=100_F=20
|
||||
###############################################################
|
||||
FITPARAMETER
|
||||
# No Name Value Step Pos_Error Boundaries
|
||||
1 zero 0 0 none
|
||||
2 phase 2.81 -0.30 0.30 0 100
|
||||
3 field 70.998 -0.025 0.025 0 none
|
||||
4 asym 0.1700 -0.0011 0.0012 0 0.3
|
||||
5 rate 0.1523 -0.0017 0.0017 0 100
|
||||
6 beta 1.255 -0.033 0.033
|
||||
7 Norm_L 2410.44 -0.83 0.83
|
||||
8 BG_L 0 0 none 0 none
|
||||
9 Norm_R 2121.43 -0.77 0.77 0 none
|
||||
10 BG_R 0 0 none 0 none
|
||||
11 relPhase 182.29 -0.31 0.31 0 none
|
||||
1 phaseL 0 0 none
|
||||
2 field 20.3390 -0.0085 0.0086 0 none
|
||||
3 asym 0.23461 -0.00051 0.00051 0 0.3
|
||||
4 rate 0.0239 -0.0040 0.0035 0 100
|
||||
5 Norm_L 1151.24 -0.53 0.53
|
||||
6 BG_L 0 0 none 0 none
|
||||
7 Norm_R 1178.60 -0.58 0.58 0 none
|
||||
8 BG_R 0 0 none 0 none
|
||||
9 relPhase 178.49 -0.20 0.20 0 none
|
||||
|
||||
###############################################################
|
||||
THEORY
|
||||
asymmetry 4
|
||||
generExpo 5 6 (rate exponent)
|
||||
asymmetry 3
|
||||
simpleGss 4 (rate)
|
||||
TFieldCos fun1 fun2 (phase frequency)
|
||||
|
||||
###############################################################
|
||||
FUNCTIONS
|
||||
fun1 = par2 + map1
|
||||
fun2 = gamma_mu * par3
|
||||
fun1 = par1 + map1
|
||||
fun2 = gamma_mu * par2
|
||||
|
||||
###############################################################
|
||||
GLOBAL
|
||||
fittype 0 (single histogram fit)
|
||||
data 40 1500
|
||||
fit 0.2 14
|
||||
data 5 2048
|
||||
t0 10.0
|
||||
deadtime-cor file
|
||||
fit 0.144 30
|
||||
packing 1
|
||||
|
||||
###############################################################
|
||||
RUN data/EMU00005989_v2 XXXX ISIS NEXUS (name beamline institute data-file-format)
|
||||
RUN data/emu00139040 EMU ISIS NEXUS (name beamline institute data-file-format)
|
||||
norm 5
|
||||
backgr.fit 6
|
||||
map 1 0 0 0 0 0 0 0 0 0
|
||||
forward 1-48
|
||||
#deadtime-cor file
|
||||
|
||||
RUN data/emu00139040 XXXX ISIS NEXUS (name beamline institute data-file-format)
|
||||
norm 7
|
||||
backgr.fit 8
|
||||
map 1 0 0 0 0 0 0 0 0 0
|
||||
forward 1-16
|
||||
|
||||
RUN data/EMU00005989_v2 XXXX ISIS NEXUS (name beamline institute data-file-format)
|
||||
norm 9
|
||||
backgr.fit 10
|
||||
map 11 0 0 0 0 0 0 0 0 0
|
||||
forward 17-32
|
||||
map 9 0 0 0 0 0 0 0 0 0
|
||||
forward 49-96
|
||||
|
||||
###############################################################
|
||||
COMMANDS
|
||||
@@ -59,15 +60,15 @@ fourier_power 11
|
||||
apodization STRONG # NONE, WEAK, MEDIUM, STRONG
|
||||
plot REAL # REAL, IMAG, REAL_AND_IMAG, POWER, PHASE, PHASE_OPT_REAL
|
||||
range 0 200
|
||||
phase parR2 par11
|
||||
phase parR1, par9
|
||||
|
||||
###############################################################
|
||||
PLOT 0 (single histo plot)
|
||||
lifetimecorrection
|
||||
runs 1 2
|
||||
range 0 14 -0.22 0.22
|
||||
view_packing 2
|
||||
range 0 20 -0.35 0.35
|
||||
view_packing 10
|
||||
|
||||
###############################################################
|
||||
STATISTIC --- 2019-03-12 18:08:05
|
||||
maxLH = 2585.1, NDF = 1696, maxLH/NDF = 1.524236
|
||||
STATISTIC --- 2026-02-21 13:06:21
|
||||
maxLH = 4233.1, NDF = 3726, maxLH/NDF = 1.136107
|
||||
|
||||
78
doc/examples/test-histo-ROOT-PPC-ADDRUN.msr
Normal file
78
doc/examples/test-histo-ROOT-PPC-ADDRUN.msr
Normal file
@@ -0,0 +1,78 @@
|
||||
LSCO(x=0.125), T=45.00 K, E=2.97 keV, B=~4(G)/0.11(A), Tr/Sa=15.02/11.30 kV, RAL-RAR=-0.01 kV, SR=-45.00
|
||||
###############################################################
|
||||
FITPARAMETER
|
||||
# Nr. Name Value Step Pos_Error Boundaries
|
||||
1 Asy 0.14561 -0.00047 0.00047 0 0.5
|
||||
2 Rate 0.1508 -0.0017 0.0017 0 10
|
||||
3 Field 29.450 -0.027 0.027 0 none
|
||||
4 N0_L 3076.3 -1.0 1.0
|
||||
5 Bkg_L 12.882 -0.071 0.071
|
||||
6 Phase_L -34.89 -0.31 0.31
|
||||
7 alpha_LR 1.16481 -0.00055 0.00055
|
||||
8 Bkg_R 17.876 -0.080 0.079
|
||||
9 RelPhase_R 163.31 -0.31 0.31
|
||||
10 Zero 0 0 none
|
||||
|
||||
###############################################################
|
||||
THEORY
|
||||
asymmetry 1
|
||||
simplExpo 2 (rate)
|
||||
TFieldCos fun3 fun1 (phase frequency)
|
||||
|
||||
###############################################################
|
||||
FUNCTIONS
|
||||
fun1 = par3 * gamma_mu
|
||||
fun2 = par7 * par4
|
||||
fun3 = par6 + map1
|
||||
|
||||
###############################################################
|
||||
GLOBAL
|
||||
data 2791 66601
|
||||
fit 0.1 12
|
||||
packing 50
|
||||
|
||||
###############################################################
|
||||
RUN data/lem15_his_2992 MUE4 PSI MUSR-ROOT (name beamline institute data-file-format)
|
||||
ADDRUN data/lem15_his_2993 MUE4 PSI MUSR-ROOT (name beamline institute data-file-format)
|
||||
ADDRUN data/lem15_his_2994 MUE4 PSI MUSR-ROOT (name beamline institute data-file-format)
|
||||
fittype 0 (single histogram fit)
|
||||
norm 4
|
||||
backgr.fit 5
|
||||
map 10 0 0 0 0 0 0 0 0 0
|
||||
forward 21 25
|
||||
|
||||
RUN data/lem15_his_2992 MUE4 PSI MUSR-ROOT (name beamline institute data-file-format)
|
||||
ADDRUN data/lem15_his_2993 MUE4 PSI MUSR-ROOT (name beamline institute data-file-format)
|
||||
ADDRUN data/lem15_his_2994 MUE4 PSI MUSR-ROOT (name beamline institute data-file-format)
|
||||
fittype 0 (single histogram fit)
|
||||
norm fun2
|
||||
backgr.fit 8
|
||||
map 9 0 0 0 0 0 0 0 0 0
|
||||
forward 23 27
|
||||
|
||||
###############################################################
|
||||
COMMANDS
|
||||
MAX_LIKELIHOOD
|
||||
MINIMIZE
|
||||
MINOS
|
||||
SAVE
|
||||
|
||||
###############################################################
|
||||
PLOT 0 (single histo plot)
|
||||
lifetimecorrection
|
||||
runs 1 2
|
||||
range 0 12 -0.2 0.2
|
||||
view_packing 500
|
||||
|
||||
###############################################################
|
||||
FOURIER
|
||||
units Gauss # units either 'Gauss', 'Tesla', 'MHz', or 'Mc/s'
|
||||
fourier_power 12
|
||||
apodization STRONG # NONE, WEAK, MEDIUM, STRONG
|
||||
plot REAL # REAL, IMAG, REAL_AND_IMAG, POWER, PHASE, PHASE_OPT_REAL
|
||||
phase par6
|
||||
range 0 700
|
||||
|
||||
###############################################################
|
||||
STATISTIC --- 2026-02-20 16:12:06
|
||||
maxLH = 2888.7, NDF = 2429, maxLH/NDF = 1.189249
|
||||
19
doc/musrStep.dox
Normal file
19
doc/musrStep.dox
Normal file
@@ -0,0 +1,19 @@
|
||||
/*********************************************************************************************
|
||||
|
||||
name: musrStep.dox
|
||||
|
||||
created by: Andreas Suter, 2025/11/24
|
||||
|
||||
content: Description of musrStep
|
||||
|
||||
**********************************************************************************************/
|
||||
|
||||
/**
|
||||
|
||||
\mainpage musrStep
|
||||
|
||||
<p>musrStep allows to reset the \<step\> values of the msr-file after a fit which went wrong. For instance this
|
||||
this is necessary for high-field muSR data, since these values might be too small for the next
|
||||
fit step.
|
||||
|
||||
*/
|
||||
2930
doc/musrStep_qt6_dox.cfg
Normal file
2930
doc/musrStep_qt6_dox.cfg
Normal file
File diff suppressed because it is too large
Load Diff
18
doc/musrWiz.dox
Normal file
18
doc/musrWiz.dox
Normal file
@@ -0,0 +1,18 @@
|
||||
/*********************************************************************************************
|
||||
|
||||
name: musrWiz.dox
|
||||
|
||||
created by: Andreas Suter, 2025/11/24
|
||||
|
||||
content: Description of musrWiz
|
||||
|
||||
**********************************************************************************************/
|
||||
|
||||
/**
|
||||
|
||||
\mainpage musrWiz -- still on the level of concept
|
||||
|
||||
<p>musrWiz allows to generate an msr-file from scratch by going through a number of questions.
|
||||
Currently only available for LEM.
|
||||
|
||||
*/
|
||||
2931
doc/musrWiz_qt6_dox.cfg
Normal file
2931
doc/musrWiz_qt6_dox.cfg
Normal file
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@
|
||||
|
||||
\mainpage musredit
|
||||
|
||||
<p>musredit is a simple editor based interface to the musrfit programs. It is based on Qt5.x or Qt6.x (depending of your distro) of The Qt Company (<code>http://www.qt.io</code>).
|
||||
<p>musredit is a simple editor based interface to the musrfit programs. It is based on Qt5.x (soon being deprecated) or Qt6.x (depending of your distro) of The Qt Company (<code>http://www.qt.io</code>).
|
||||
|
||||
<p>musredit is free software liensenced under GPL 2 or later (for detail license informations see
|
||||
<code>http://www.gnu.org/licenses</code>).
|
||||
|
||||
@@ -47,10 +47,12 @@ under Linux, Mac OS X, and (with some more work) under Windows. The musrfit fram
|
||||
msr-files with the same parameters and summarize the fitting results either in a TRIUMF DB or a column ASCII file.
|
||||
- **msr2msr**: old WKM like msr-files can be transformed into musrfit style msr-files with this little program.
|
||||
- musrgui (obsolete): an editor to handle msr-files, calling musrfit, etc. from within the editor, based on Qt3.x.
|
||||
- **musredit**: an editor to handle msr-files, calling musrfit, etc. from within a simple text editor, based on Qt5.x or Qt6.x. A technical documentation of musredit can be found
|
||||
- **musredit**: an editor to handle msr-files, calling musrfit, etc. from within a simple text editor, based on Qt5.x (soon being deprecated) or Qt6.x. A technical documentation of musredit can be found
|
||||
\htmlonly <a href="./musredit/html/index.html">here.</a>\endhtmlonly
|
||||
- **musrWiz** (beta): allows to create an initial msr-file by a step-by-step instruction wizard.
|
||||
- **musrStep**: allows to efficiently deal with initial step values of msr-files. Especially useful for msr-files dealing with many runs/detectors.
|
||||
- **musrWiz** (beta): allows to create an initial msr-file by a step-by-step instruction wizard. A technical documentation of musrWiz can be found
|
||||
\htmlonly <a href="./musrWiz/html/index.html">here.</a>\endhtmlonly
|
||||
- **musrStep**: allows to efficiently deal with initial step values of msr-files. Especially useful for msr-files dealing with many runs/detectors. A technical documentation of musrStep can be found
|
||||
\htmlonly <a href="./musrStep/html/index.html">here.</a>\endhtmlonly
|
||||
- **mupp**: is the muSR parameter plotter. It allows to plot values in db- or dat-files (collections). A technical documentation of mupp can be found
|
||||
\htmlonly <a href="./mupp/html/index.html">here.</a>\endhtmlonly
|
||||
- **addRun**: allows to add runs from the command line
|
||||
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = musrfit
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 1.9.9
|
||||
PROJECT_NUMBER = 1.10.0
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
@@ -923,6 +923,18 @@ INPUT = musrfit.dox \
|
||||
../src/classes/PUserFcn.cpp \
|
||||
../src/external/MusrRoot/TMusrRunHeader.h \
|
||||
../src/external/MusrRoot/TMusrRunHeader.cpp \
|
||||
../src/external/nexus/PNeXus.h \
|
||||
../src/external/nexus/PNeXus.cpp \
|
||||
../src/external/MuSR_software/Class_MuSR_PSI/MuSR_td_PSI_bin.h \
|
||||
../src/external/MuSR_software/Class_MuSR_PSI/MuSR_td_PSI_bin.cpp \
|
||||
../src/external/mud/src/mud.h \
|
||||
../src/external/mud/src/mud_all.c \
|
||||
../src/external/mud/src/mud.c \
|
||||
../src/external/mud/src/mud_encode.c \
|
||||
../src/external/mud/src/mud_friendly.c \
|
||||
../src/external/mud/src/mud_gen.c \
|
||||
../src/external/mud/src/mud_new.c \
|
||||
../src/external/mud/src/mud_tri_ti.c \
|
||||
../src/addRun.cpp \
|
||||
../src/any2many.cpp \
|
||||
../src/dump_header.cpp \
|
||||
@@ -2241,7 +2253,7 @@ INCLUDE_FILE_PATTERNS =
|
||||
# recursively expanded use the := operator instead of the = operator.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED =
|
||||
PREDEFINED = HAVE_HDF4
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
# tag can be used to specify a list of macro names that should be expanded. The
|
||||
@@ -2280,7 +2292,9 @@ SKIP_FUNCTION_MACROS = YES
|
||||
# run, you must also specify the path to the tagfile here.
|
||||
|
||||
TAGFILES = dox-tags/musredit.tag=musredit/html \
|
||||
dox-tags/mupp.tag=mupp/html
|
||||
dox-tags/mupp.tag=mupp/html \
|
||||
dox-tags/musrStep.tag=musrStep/html \
|
||||
dox-tags/musrWiz.tag=musrWiz/html
|
||||
|
||||
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
|
||||
# tag file that is based on the input files it reads. See section "Linking to
|
||||
|
||||
@@ -23,7 +23,7 @@ endif (nexus)
|
||||
set(MUSRFIT_LIBS ${MUSRFIT_LIBS} PMusr)
|
||||
|
||||
#--- add all executables ------------------------------------------------------
|
||||
add_executable(addRun ${GIT_REV_H} addRun.cpp)
|
||||
add_executable(addRun addRun.cpp)
|
||||
target_compile_options(addRun BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")
|
||||
target_include_directories(addRun
|
||||
BEFORE PRIVATE
|
||||
@@ -34,7 +34,7 @@ target_include_directories(addRun
|
||||
)
|
||||
target_link_libraries(addRun ${ROOT_LIBRARIES} ${MUSRFIT_LIBS} ${Boost_LIBRARIES})
|
||||
|
||||
add_executable(any2many ${GIT_REV_H} any2many.cpp)
|
||||
add_executable(any2many any2many.cpp)
|
||||
target_compile_options(any2many BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")
|
||||
target_include_directories(any2many
|
||||
BEFORE PRIVATE
|
||||
@@ -45,12 +45,13 @@ target_include_directories(any2many
|
||||
)
|
||||
target_link_libraries(any2many ${ROOT_LIBRARIES} ${MUSRFIT_LIBS})
|
||||
|
||||
add_executable(dump_header ${GIT_REV_H} dump_header.cpp)
|
||||
add_executable(dump_header dump_header.cpp)
|
||||
target_compile_options(dump_header BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")
|
||||
target_include_directories(dump_header
|
||||
BEFORE PRIVATE
|
||||
$<BUILD_INTERFACE:${Boost_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${NEXUS_INCLUDE_DIR}>
|
||||
$<BUILD_INTERFACE:${HDF4_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${HDF5_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/src>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/include>
|
||||
@@ -62,7 +63,7 @@ target_include_directories(dump_header
|
||||
)
|
||||
target_link_libraries(dump_header ${ROOT_LIBRARIES} ${MUSRFIT_LIBS})
|
||||
|
||||
add_executable(msr2data ${GIT_REV_H} msr2data.cpp)
|
||||
add_executable(msr2data msr2data.cpp)
|
||||
target_compile_options(msr2data BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")
|
||||
target_include_directories(msr2data
|
||||
BEFORE PRIVATE
|
||||
@@ -76,7 +77,7 @@ target_link_libraries(msr2data ${ROOT_LIBRARIES} ${MUSRFIT_LIBS})
|
||||
add_executable(msr2msr msr2msr.cpp)
|
||||
target_link_libraries(msr2msr ${ROOT_LIBRARIES})
|
||||
|
||||
add_executable(musrfit ${GIT_REV_H} musrfit.cpp)
|
||||
add_executable(musrfit musrfit.cpp)
|
||||
target_compile_options(musrfit BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")
|
||||
target_include_directories(musrfit
|
||||
BEFORE PRIVATE
|
||||
@@ -87,7 +88,7 @@ target_include_directories(musrfit
|
||||
)
|
||||
target_link_libraries(musrfit ${ROOT_LIBRARIES} ${MUSRFIT_LIBS})
|
||||
|
||||
add_executable(musrFT ${GIT_REV_H} musrFT.cpp)
|
||||
add_executable(musrFT musrFT.cpp)
|
||||
target_compile_options(musrFT BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")
|
||||
target_include_directories(musrFT
|
||||
BEFORE PRIVATE
|
||||
@@ -99,7 +100,7 @@ target_include_directories(musrFT
|
||||
)
|
||||
target_link_libraries(musrFT FFTW3::FFTW3 ${ROOT_LIBRARIES} ${MUSRFIT_LIBS})
|
||||
|
||||
add_executable(musrRootValidation ${GIT_REV_H} musrRootValidation.cpp)
|
||||
add_executable(musrRootValidation musrRootValidation.cpp)
|
||||
target_compile_options(musrRootValidation BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")
|
||||
target_include_directories(musrRootValidation
|
||||
BEFORE PRIVATE
|
||||
@@ -110,7 +111,7 @@ target_include_directories(musrRootValidation
|
||||
)
|
||||
target_link_libraries(musrRootValidation ${ROOT_LIBRARIES} ${MUSRFIT_LIBS} ${LIBXML2_LIBRARIES})
|
||||
|
||||
add_executable(musrt0 ${GIT_REV_H} musrt0.cpp)
|
||||
add_executable(musrt0 musrt0.cpp)
|
||||
target_compile_options(musrt0 BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")
|
||||
target_include_directories(musrt0
|
||||
BEFORE PRIVATE
|
||||
@@ -121,7 +122,7 @@ target_include_directories(musrt0
|
||||
)
|
||||
target_link_libraries(musrt0 ${ROOT_LIBRARIES} ${MUSRFIT_LIBS})
|
||||
|
||||
add_executable(musrview ${GIT_REV_H} musrview.cpp)
|
||||
add_executable(musrview musrview.cpp)
|
||||
target_compile_options(musrview BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")
|
||||
target_include_directories(musrview
|
||||
BEFORE PRIVATE
|
||||
@@ -133,7 +134,7 @@ target_include_directories(musrview
|
||||
)
|
||||
target_link_libraries(musrview FFTW3::FFTW3 ${ROOT_LIBRARIES} ${MUSRFIT_LIBS})
|
||||
|
||||
add_executable(write_musrRoot_runHeader ${GIT_REV_H} write_musrRoot_runHeader.cpp)
|
||||
add_executable(write_musrRoot_runHeader write_musrRoot_runHeader.cpp)
|
||||
target_compile_options(write_musrRoot_runHeader BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")
|
||||
target_include_directories(write_musrRoot_runHeader
|
||||
BEFORE PRIVATE
|
||||
@@ -145,6 +146,20 @@ target_include_directories(write_musrRoot_runHeader
|
||||
)
|
||||
target_link_libraries(write_musrRoot_runHeader ${ROOT_LIBRARIES} ${MUSRFIT_LIBS} ${LIBXML2_LIBRARIES})
|
||||
|
||||
#--- ensure git-revision.h is regenerated before compiling --------------------
|
||||
if (IS_GIT_REPO)
|
||||
add_dependencies(addRun git_revision)
|
||||
add_dependencies(any2many git_revision)
|
||||
add_dependencies(dump_header git_revision)
|
||||
add_dependencies(msr2data git_revision)
|
||||
add_dependencies(musrfit git_revision)
|
||||
add_dependencies(musrFT git_revision)
|
||||
add_dependencies(musrRootValidation git_revision)
|
||||
add_dependencies(musrt0 git_revision)
|
||||
add_dependencies(musrview git_revision)
|
||||
add_dependencies(write_musrRoot_runHeader git_revision)
|
||||
endif (IS_GIT_REPO)
|
||||
|
||||
#--- installation info --------------------------------------------------------
|
||||
install(
|
||||
TARGETS
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -168,6 +168,8 @@ bool addRun_readInputFiles(const std::string fileName, std::vector<PAddRunInfo>
|
||||
char *tok{nullptr};
|
||||
int status, ival;
|
||||
bool lastWasFile{false};
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
memset(str, '\0', sizeof(str));
|
||||
while (fin.good()) {
|
||||
fin.getline(buf, 256);
|
||||
line = buf;
|
||||
@@ -176,7 +178,7 @@ bool addRun_readInputFiles(const std::string fileName, std::vector<PAddRunInfo>
|
||||
continue;
|
||||
if (line[0] == '%')
|
||||
continue;
|
||||
strcpy(buf, line.c_str());
|
||||
strncpy(buf, line.c_str(), sizeof(buf));
|
||||
tok = strtok(buf, " ");
|
||||
if (!strcmp(tok, "file")) {
|
||||
if (lastWasFile) {
|
||||
@@ -242,6 +244,10 @@ bool addRun_readInputFiles(const std::string fileName, std::vector<PAddRunInfo>
|
||||
UInt_t addRun_getPromptPeakPos(PDoubleVector *vec)
|
||||
{
|
||||
UInt_t pos=0;
|
||||
|
||||
if (vec == nullptr)
|
||||
return pos;
|
||||
|
||||
Double_t max=vec->at(0);
|
||||
|
||||
for (UInt_t i=0; i<vec->size(); i++) {
|
||||
@@ -536,13 +542,14 @@ int main(int argc, char *argv[])
|
||||
|
||||
// read startup file
|
||||
char startup_path_name[128];
|
||||
memset(startup_path_name, '\0', sizeof(startup_path_name));
|
||||
std::unique_ptr<TSAXParser> saxParser = std::make_unique<TSAXParser>();
|
||||
std::unique_ptr<PStartupHandler> startupHandler = std::make_unique<PStartupHandler>();
|
||||
if (!startupHandler->StartupFileFound()) {
|
||||
std::cerr << std::endl << ">> addRun **WARNING** couldn't find " << startupHandler->GetStartupFilePath().Data();
|
||||
std::cerr << std::endl;
|
||||
} else {
|
||||
strcpy(startup_path_name, startupHandler->GetStartupFilePath().Data());
|
||||
strncpy(startup_path_name, startupHandler->GetStartupFilePath().Data(), sizeof(startup_path_name));
|
||||
saxParser->ConnectToHandler("PStartupHandler", startupHandler.get());
|
||||
//status = saxParser->ParseFile(startup_path_name);
|
||||
// parsing the file as above seems to lead to problems in certain environments;
|
||||
@@ -678,7 +685,7 @@ int main(int argc, char *argv[])
|
||||
if (isGood) {
|
||||
// check that all runs have the same number of histograms
|
||||
for (UInt_t i=1; i<runDataHandler.size(); i++) {
|
||||
if (runDataHandler[0]->GetRunData()->GetNoOfHistos() != runDataHandler[0]->GetRunData()->GetNoOfHistos()) {
|
||||
if (runDataHandler[0]->GetRunData()->GetNoOfHistos() != runDataHandler[i]->GetRunData()->GetNoOfHistos()) {
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "**ERROR** can only add runs with the same number of histograms." << std::endl;
|
||||
std::cerr << std::endl;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -423,7 +423,7 @@ int main(int argc, char *argv[])
|
||||
} else if (!strcmp(argv[i], "-z")) { // filter out if compression is whished
|
||||
if (i+2 < argc) {
|
||||
if ((argv[i+1][0] == '-') || (argv[i+2][0] == '-')) {
|
||||
std::cerr << std::endl << ">> any2many **ERROR** found invalid template in option '-t'" << std::endl;
|
||||
std::cerr << std::endl << ">> any2many **ERROR** found invalid template in option '-z'" << std::endl;
|
||||
show_syntax = true;
|
||||
break;
|
||||
}
|
||||
@@ -499,13 +499,14 @@ int main(int argc, char *argv[])
|
||||
|
||||
// read startup file
|
||||
char startup_path_name[128];
|
||||
memset(startup_path_name, '\0', sizeof(startup_path_name));
|
||||
std::unique_ptr<TSAXParser> saxParser = std::make_unique<TSAXParser>();
|
||||
std::unique_ptr<PStartupHandler> startupHandler = std::make_unique<PStartupHandler>();
|
||||
if (!startupHandler->StartupFileFound()) {
|
||||
std::cerr << std::endl << ">> any2many **WARNING** couldn't find " << startupHandler->GetStartupFilePath().Data();
|
||||
std::cerr << std::endl;
|
||||
} else {
|
||||
strcpy(startup_path_name, startupHandler->GetStartupFilePath().Data());
|
||||
strncpy(startup_path_name, startupHandler->GetStartupFilePath().Data(), sizeof(startup_path_name));
|
||||
saxParser->ConnectToHandler("PStartupHandler", startupHandler.get());
|
||||
//status = saxParser->ParseFile(startup_path_name);
|
||||
// parsing the file as above seems to lead to problems in certain environments;
|
||||
|
||||
@@ -82,7 +82,7 @@ set(prefix "${CMAKE_INSTALL_PREFIX}")
|
||||
set(exec_prefix "\$\{prefix\}")
|
||||
set(libdir "\$\{exec_prefix\}/lib")
|
||||
set(includedir "\$\{prefix\}/include")
|
||||
set(MUSR_VERSION "1.6.0")
|
||||
set(MUSR_VERSION "1.8.0")
|
||||
set(MUSR_LIBRARY_NAME "PMusr")
|
||||
configure_file("PMusr.pc.in" "PMusr.pc" @ONLY)
|
||||
set(USERFCN_LIBRARY_NAME "PUserFcnBase")
|
||||
@@ -131,13 +131,15 @@ target_include_directories(
|
||||
PMusr BEFORE PRIVATE
|
||||
$<BUILD_INTERFACE:${Boost_INCLUDE_DIR}>
|
||||
$<BUILD_INTERFACE:${FFTW3_INCLUDE}>
|
||||
$<BUILD_INTERFACE:${NEXUS_INCLUDE_DIR}>
|
||||
$<BUILD_INTERFACE:${HDF4_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${HDF5_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${MUSRFIT_INC}>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/external/MusrRoot>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/external/TLemRunHeader>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/external/MuSR_software/Class_MuSR_PSI>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/external/mud/src>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/external/nexus>
|
||||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
|
||||
)
|
||||
|
||||
add_library(PUserFcnBase SHARED
|
||||
@@ -151,6 +153,7 @@ add_library(PRgeHandler SHARED
|
||||
)
|
||||
|
||||
#--- set target properties, e.g. version --------------------------------------
|
||||
target_compile_options(PMusr BEFORE PRIVATE "-DHAVE_CONFIG_H")
|
||||
set_target_properties(PMusr
|
||||
PROPERTIES
|
||||
VERSION ${MUSR_VERSION}
|
||||
@@ -232,13 +235,16 @@ install(
|
||||
|
||||
#--- install headers ----------------------------------------------------------
|
||||
install(
|
||||
FILES ${MUSRFIT_INC}/PFitterFcn.h
|
||||
FILES ${MUSRFIT_INC}/PFindRun.h
|
||||
${MUSRFIT_INC}/PFitterFcn.h
|
||||
${MUSRFIT_INC}/PFitter.h
|
||||
${MUSRFIT_INC}/PFourierCanvas.h
|
||||
${MUSRFIT_INC}/PFourier.h
|
||||
${MUSRFIT_INC}/PFourier.h
|
||||
${MUSRFIT_INC}/PFunctionAst.h
|
||||
${MUSRFIT_INC}/PFunctionGrammar.h
|
||||
${MUSRFIT_INC}/PFunction.h
|
||||
${MUSRFIT_INC}/PFunctionHandler.h
|
||||
${MUSRFIT_INC}/PMsgBox.h
|
||||
${MUSRFIT_INC}/PMsr2Data.h
|
||||
${MUSRFIT_INC}/PMsrHandler.h
|
||||
${MUSRFIT_INC}/PMusrCanvas.h
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -260,11 +260,32 @@ UInt_t PSectorChisq::GetNDF(UInt_t idx)
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor.
|
||||
* @brief Constructor for the fitting engine.
|
||||
*
|
||||
* \param runInfo pointer of the msr-file handler
|
||||
* \param runListCollection pointer of the run list collection (pre-processed historgrams)
|
||||
* \param chisq_only flag: true=calculate chisq only (no fitting)
|
||||
* Initializes the fitter with MSR configuration and preprocessed data.
|
||||
* Sets up the fitting environment including:
|
||||
* - Parameter lists and command queues
|
||||
* - Fit mode (χ² vs. likelihood)
|
||||
* - Strategy and print level defaults
|
||||
* - Original fit ranges for RANGE commands
|
||||
* - Phase parameter identification
|
||||
*
|
||||
* The constructor validates the COMMANDS block and creates the objective
|
||||
* function (PFitterFcn) but does not start the fit. Call DoFit() to execute.
|
||||
*
|
||||
* @param runInfo Pointer to MSR file handler containing fit configuration
|
||||
* @param runListCollection Pointer to preprocessed data collection
|
||||
* @param chisq_only If true, only evaluate χ² without fitting (useful for validation)
|
||||
* @param yaml_out If true, generate YAML output file with fit results
|
||||
*
|
||||
* @note Sets fIsValid = false if command validation fails. Check IsValid() before DoFit().
|
||||
*
|
||||
* @par Initialization sequence:
|
||||
* 1. Copy parameters and commands from MSR handler
|
||||
* 2. Store original fit ranges (for FIT_RANGE command)
|
||||
* 3. Parse and validate COMMANDS block
|
||||
* 4. Identify phase parameters (for angle wrapping)
|
||||
* 5. Create objective function interface
|
||||
*/
|
||||
PFitter::PFitter(PMsrHandler *runInfo, PRunListCollection *runListCollection, Bool_t chisq_only, Bool_t yaml_out) :
|
||||
fChisqOnly(chisq_only), fYamlOut(yaml_out), fRunInfo(runInfo), fRunListCollection(runListCollection)
|
||||
@@ -323,7 +344,10 @@ PFitter::PFitter(PMsrHandler *runInfo, PRunListCollection *runListCollection, Bo
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor.
|
||||
* @brief Destructor - Cleans up dynamically allocated resources.
|
||||
*
|
||||
* Frees memory used by command lists, scan data, and timing information.
|
||||
* Smart pointers (fFitterFcn, fFcnMin) are automatically cleaned up.
|
||||
*/
|
||||
PFitter::~PFitter()
|
||||
{
|
||||
@@ -338,8 +362,30 @@ PFitter::~PFitter()
|
||||
// GetPhaseParams (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Checks which parameters are phases. This information is needed to
|
||||
* restrict the phases to the intervall -360 to +360 degrees.
|
||||
* @brief Identifies which parameters represent phase angles.
|
||||
*
|
||||
* Scans the THEORY block to detect parameters used as phases in standard
|
||||
* muSR functions. Phase parameters are flagged to enable automatic wrapping
|
||||
* to the interval [-360°, +360°] during fitting, preventing meaningless
|
||||
* phase values outside this range.
|
||||
*
|
||||
* Recognized phase-containing functions:
|
||||
* - TFieldCos/tf: phase is 1st parameter
|
||||
* - bessel/b: phase is 1st parameter
|
||||
* - skewedGss/skg: phase is 1st parameter
|
||||
* - staticNKTF/snktf: phase is 1st parameter
|
||||
* - dynamicNKTF/dnktf: phase is 1st parameter
|
||||
* - internFld/if: phase is 2nd parameter
|
||||
* - internBsl/ib: phase is 2nd parameter
|
||||
* - muMinusExpTF/mmsetf: phase is 5th parameter
|
||||
*
|
||||
* Phase references can be:
|
||||
* - Direct parameter numbers (e.g., "7" → par7)
|
||||
* - Function references (e.g., "fun3" → all params in function 3)
|
||||
* - Map references (e.g., "map2" → parameters mapped across runs)
|
||||
*
|
||||
* @note Populates fPhase vector where fPhase[i] = true means parameter i+1 is a phase.
|
||||
* @note User-defined functions cannot be automatically analyzed for phases.
|
||||
*/
|
||||
void PFitter::GetPhaseParams()
|
||||
{
|
||||
@@ -423,11 +469,22 @@ void PFitter::GetPhaseParams()
|
||||
// GetParFromFun (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Extract from string funX the function number. Base on the function number
|
||||
* the paramter numbers will be collected.
|
||||
* @brief Extracts parameter numbers from a FUNCTIONS block entry.
|
||||
*
|
||||
* @param funStr string of the form funX, where X is the function number
|
||||
* @return a vector of all the parameter numbers related to funX
|
||||
* Parses a function definition to find all parameters it references.
|
||||
* Recursively handles nested map references within the function.
|
||||
*
|
||||
* @param funStr Function identifier (e.g., "fun1", "fun23")
|
||||
* @return Vector of parameter numbers (1-indexed) used in the function
|
||||
*
|
||||
* @par Example:
|
||||
* If FUNCTIONS block contains:
|
||||
* @code
|
||||
* fun1 = par3 * par7 + map2
|
||||
* @endcode
|
||||
* Then GetParFromFun("fun1") returns [3, 7, ...params from map2...]
|
||||
*
|
||||
* @note Returns empty vector if function not found or parsing fails.
|
||||
*/
|
||||
PIntVector PFitter::GetParFromFun(const TString funStr)
|
||||
{
|
||||
@@ -490,11 +547,25 @@ PIntVector PFitter::GetParFromFun(const TString funStr)
|
||||
// GetParFromMap (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Extract from string mapX the map number. Based on the map number the
|
||||
* parameter numbers will be collected.
|
||||
* @brief Extracts parameter numbers from a map reference.
|
||||
*
|
||||
* @param mapStr string of the form mapX, where X is the map number
|
||||
* @return a vector of all the parameter numbers related to mapX
|
||||
* Parses "mapX" to find which parameters are mapped to the X-th position
|
||||
* across all RUN blocks. Maps allow different runs to use different parameters
|
||||
* for the same theoretical component, enabling multi-run fits with run-dependent
|
||||
* parameters.
|
||||
*
|
||||
* @param mapStr Map identifier (e.g., "map1", "map5")
|
||||
* @return Vector of parameter numbers (1-indexed) mapped at this position
|
||||
*
|
||||
* @par Example:
|
||||
* If RUN blocks have:
|
||||
* @code
|
||||
* RUN 1: map 7 8 9
|
||||
* RUN 2: map 10 11 12
|
||||
* @endcode
|
||||
* Then GetParFromMap("map1") returns [7, 10] (first map entry per run)
|
||||
*
|
||||
* @note Returns empty vector if map index is out of range or invalid.
|
||||
*/
|
||||
PIntVector PFitter::GetParFromMap(const TString mapStr)
|
||||
{
|
||||
@@ -541,9 +612,37 @@ PIntVector PFitter::GetParFromMap(const TString mapStr)
|
||||
// DoFit
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Main calling routine to invoke minuit2, i.e. fitting etc.
|
||||
* @brief Main entry point for executing the fit.
|
||||
*
|
||||
* <b>return:</b> true if all commands could be executed successfully, otherwise returns false.
|
||||
* This is the primary method that orchestrates the entire fitting process:
|
||||
* 1. Transfers parameters from MSR to Minuit2
|
||||
* 2. If chisq_only mode: calculates χ²/maxLH and returns
|
||||
* 3. Otherwise: executes COMMANDS block sequentially
|
||||
* 4. Updates MSR file with fit results and statistics
|
||||
*
|
||||
* @return true if fit completed successfully (or chisq calculated), false on errors
|
||||
*
|
||||
* @par Execution modes:
|
||||
* - **chisq_only = true:** Evaluates objective function once with current parameters,
|
||||
* reports χ²/maxLH and NDF, useful for validating parameter sets
|
||||
* - **chisq_only = false:** Runs full fit according to COMMANDS block, which typically
|
||||
* includes MIGRAD (minimization), HESSE (error matrix), optionally MINOS (asymmetric errors)
|
||||
*
|
||||
* @par COMMANDS execution:
|
||||
* Commands are executed in the order they appear in the MSR file. Common sequence:
|
||||
* @code
|
||||
* SET PRINT 1 # Set verbosity
|
||||
* MIGRAD # Find minimum
|
||||
* HESSE # Calculate symmetric errors
|
||||
* MINOS # Calculate asymmetric errors (optional)
|
||||
* SAVE # Save results to MSR file
|
||||
* @endcode
|
||||
*
|
||||
* @note Check IsValid() before calling. Check HasConverged() after completion.
|
||||
* @note Updates fRunInfo with final parameters, errors, and fit statistics.
|
||||
* @note Prints detailed χ² breakdown per run if multiple runs are fitted.
|
||||
*
|
||||
* @see ExecuteMigrad(), ExecuteHesse(), ExecuteMinos(), ExecuteSave()
|
||||
*/
|
||||
Bool_t PFitter::DoFit()
|
||||
{
|
||||
@@ -825,10 +924,31 @@ Bool_t PFitter::DoFit()
|
||||
// CheckCommands
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Check the msr-file COMMAND's, fill the command queue and make sure that given parameters (if present)
|
||||
* do make any sense.
|
||||
* @brief Validates COMMANDS block and builds execution queue.
|
||||
*
|
||||
* <b>return:</b> true if the commands are valid, otherwise returns false.
|
||||
* Parses all command lines from the MSR file's COMMANDS block, validates
|
||||
* syntax and parameters, and constructs an ordered execution list. This
|
||||
* ensures commands are executable before starting the fit.
|
||||
*
|
||||
* @return true if all commands are valid and parseable, false on any error
|
||||
*
|
||||
* @par Validation checks:
|
||||
* - Command keywords are recognized (MIGRAD, HESSE, MINOS, etc.)
|
||||
* - Numeric arguments are valid (parameter indices, ranges, point counts)
|
||||
* - Parameter references are within bounds
|
||||
* - SCAN/CONTOURS have required arguments
|
||||
* - FIX/RELEASE specify valid parameter lists
|
||||
*
|
||||
* @par Side effects:
|
||||
* - Populates fCmdList with (command_ID, line_number) pairs
|
||||
* - Sets fIsValid = false if any command is invalid
|
||||
* - Configures scan parameters (fScanParameter, fScanNoPoints, etc.)
|
||||
* - Detects SECTOR command presence (sets fSectorFlag)
|
||||
*
|
||||
* @note Called automatically by constructor. Errors are reported to stderr.
|
||||
* @note Some legacy commands (SET BATCH, END RETURN) are silently ignored.
|
||||
*
|
||||
* @see PMN_* command constants in PFitter.h
|
||||
*/
|
||||
Bool_t PFitter::CheckCommands()
|
||||
{
|
||||
@@ -2396,7 +2516,7 @@ Bool_t PFitter::ExecuteSave(Bool_t firstSave)
|
||||
// write correlation matrix
|
||||
fout << std::endl << " CORRELATION COEFFICIENTS";
|
||||
fout << std::endl << "-------------------------------------------------------------------------";
|
||||
if (mnState.HasGlobalCC() && mnState.HasCovariance()) {
|
||||
if (mnState.IsValid() && mnState.HasCovariance()) {
|
||||
ROOT::Minuit2::MnGlobalCorrelationCoeff corr = mnState.GlobalCC();
|
||||
ROOT::Minuit2::MnUserCovariance cov = mnState.Covariance();
|
||||
PIntVector parNo;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -51,7 +51,18 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Default constructor for phase correction optimizer.
|
||||
*
|
||||
* <p>Initializes a phase correction object with default Fourier data.
|
||||
* The actual Fourier data must be set externally before minimization.
|
||||
*
|
||||
* @param minBin Minimum frequency bin index for optimization region.
|
||||
* Use -1 to optimize over all bins. Default: -1.
|
||||
* @param maxBin Maximum frequency bin index for optimization region.
|
||||
* Use -1 to optimize over all bins. Default: -1.
|
||||
*
|
||||
* <p><b>Note:</b> Restricting the optimization range to signal-containing
|
||||
* regions improves results by excluding noisy baseline regions.
|
||||
*/
|
||||
PFTPhaseCorrection::PFTPhaseCorrection(const Int_t minBin, const Int_t maxBin) :
|
||||
fMinBin(minBin), fMaxBin(maxBin)
|
||||
@@ -63,7 +74,28 @@ PFTPhaseCorrection::PFTPhaseCorrection(const Int_t minBin, const Int_t maxBin) :
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor with explicit Fourier transform data.
|
||||
*
|
||||
* <p>Creates a phase correction optimizer with pre-computed Fourier data.
|
||||
* The optimizer will find phase parameters φ(ω) = c₀ + c₁·ω that maximize
|
||||
* the real component while minimizing the imaginary component.
|
||||
*
|
||||
* @param reFT Real part of the Fourier transform (vector of amplitudes).
|
||||
* @param imFT Imaginary part of the Fourier transform (vector of amplitudes).
|
||||
* @param minBin Minimum frequency bin index for optimization region.
|
||||
* Use -1 to optimize over all bins. Default: -1.
|
||||
* @param maxBin Maximum frequency bin index for optimization region.
|
||||
* Use -1 to optimize over all bins. Default: -1.
|
||||
*
|
||||
* <p><b>Usage example:</b>
|
||||
* @code
|
||||
* std::vector<Double_t> real, imag;
|
||||
* // ... fill real and imag with FFT results ...
|
||||
* PFTPhaseCorrection phCorr(real, imag, 10, 500);
|
||||
* phCorr.Minimize();
|
||||
* Double_t c0 = phCorr.GetPhaseCorrectionParam(0);
|
||||
* Double_t c1 = phCorr.GetPhaseCorrectionParam(1);
|
||||
* @endcode
|
||||
*/
|
||||
PFTPhaseCorrection::PFTPhaseCorrection(std::vector<Double_t> &reFT, std::vector<Double_t> &imFT, const Int_t minBin, const Int_t maxBin) :
|
||||
fReal(reFT), fImag(imFT), fMinBin(minBin), fMaxBin(maxBin)
|
||||
@@ -86,7 +118,28 @@ PFTPhaseCorrection::PFTPhaseCorrection(std::vector<Double_t> &reFT, std::vector<
|
||||
// Minimize (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Performs phase correction minimization using Minuit2.
|
||||
*
|
||||
* <p>This method finds optimal phase parameters (c₀, c₁) by minimizing
|
||||
* a combined entropy-penalty functional:
|
||||
* - <b>Entropy term:</b> Promotes smooth, concentrated real spectra
|
||||
* - <b>Penalty term:</b> Penalizes negative values in real spectrum
|
||||
*
|
||||
* <p>The phase correction is: φ(ω) = c₀ + c₁·ω where:
|
||||
* - c₀ corrects constant phase offset (time-zero uncertainty)
|
||||
* - c₁ corrects linear phase dispersion (detector timing effects)
|
||||
*
|
||||
* <p><b>Algorithm:</b>
|
||||
* 1. Initialize Minuit2 parameters with starting values (c₀=0, c₁=0)
|
||||
* 2. Minimize entropy + γ×penalty using MnMinimize
|
||||
* 3. Store optimal parameters in fPh_c0, fPh_c1
|
||||
*
|
||||
* <p>After calling this method, use GetPhaseCorrectionParam() to retrieve
|
||||
* the optimal phase parameters and IsValid() to check success.
|
||||
*
|
||||
* @see GetPhaseCorrectionParam()
|
||||
* @see SetGamma()
|
||||
* @see IsValid()
|
||||
*/
|
||||
void PFTPhaseCorrection::Minimize()
|
||||
{
|
||||
@@ -118,7 +171,26 @@ void PFTPhaseCorrection::Minimize()
|
||||
// GetPhaseCorrectionParam (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Retrieves optimized phase correction parameter by index.
|
||||
*
|
||||
* <p>Returns the phase parameter determined by Minimize(). The phase
|
||||
* correction formula is: φ(ω) = c₀ + c₁·(ω/ω_max)
|
||||
*
|
||||
* @param idx Parameter index:
|
||||
* - 0: Returns c₀ (constant phase offset in radians)
|
||||
* - 1: Returns c₁ (linear phase dispersion coefficient)
|
||||
*
|
||||
* @return Phase correction parameter value, or 0.0 if idx is invalid.
|
||||
*
|
||||
* <p><b>Example:</b>
|
||||
* @code
|
||||
* phCorr.Minimize();
|
||||
* if (phCorr.IsValid()) {
|
||||
* Double_t c0 = phCorr.GetPhaseCorrectionParam(0);
|
||||
* Double_t c1 = phCorr.GetPhaseCorrectionParam(1);
|
||||
* std::cout << "Phase: " << c0 << " + " << c1 << "*w" << std::endl;
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
Double_t PFTPhaseCorrection::GetPhaseCorrectionParam(UInt_t idx)
|
||||
{
|
||||
@@ -138,7 +210,15 @@ Double_t PFTPhaseCorrection::GetPhaseCorrectionParam(UInt_t idx)
|
||||
// GetMinimum (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Returns the minimum value of the optimization functional.
|
||||
*
|
||||
* <p>This value represents the combined entropy-penalty functional at
|
||||
* the optimal phase parameters. Lower values indicate better phase
|
||||
* correction. A value of -1.0 indicates failed minimization.
|
||||
*
|
||||
* @return Minimum functional value, or -1.0 if minimization failed.
|
||||
*
|
||||
* <p><b>Note:</b> Always check IsValid() before using this value.
|
||||
*/
|
||||
Double_t PFTPhaseCorrection::GetMinimum()
|
||||
{
|
||||
@@ -154,7 +234,16 @@ Double_t PFTPhaseCorrection::GetMinimum()
|
||||
// Init (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Initializes phase correction object with default values.
|
||||
*
|
||||
* <p>Sets initial state:
|
||||
* - fValid = true (object ready for use)
|
||||
* - fPh_c0 = 0.0 (no constant phase offset)
|
||||
* - fPh_c1 = 0.0 (no linear phase dispersion)
|
||||
* - fGamma = 1.0 (equal weighting of entropy and penalty)
|
||||
* - fMin = -1.0 (no minimization performed yet)
|
||||
*
|
||||
* <p>Called by constructors to establish consistent initial state.
|
||||
*/
|
||||
void PFTPhaseCorrection::Init()
|
||||
{
|
||||
@@ -169,7 +258,20 @@ void PFTPhaseCorrection::Init()
|
||||
// CalcPhasedFT (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculates phase-corrected Fourier transform.
|
||||
*
|
||||
* <p>Applies the phase correction φ(ω) = c₀ + c₁·(i/N) to the complex
|
||||
* Fourier spectrum using rotation in the complex plane:
|
||||
* - F'_re(ω) = F_re(ω)·cos(φ) - F_im(ω)·sin(φ)
|
||||
* - F'_im(ω) = F_re(ω)·sin(φ) + F_im(ω)·cos(φ)
|
||||
*
|
||||
* <p>The corrected spectra are stored in fRealPh and fImagPh.
|
||||
*
|
||||
* <p><b>Physics:</b> This rotation compensates for:
|
||||
* - Time-zero offset (constant phase c₀)
|
||||
* - Timing dispersion (linear phase c₁)
|
||||
*
|
||||
* @see CalcRealPhFTDerivative()
|
||||
*/
|
||||
void PFTPhaseCorrection::CalcPhasedFT() const
|
||||
{
|
||||
@@ -188,7 +290,19 @@ void PFTPhaseCorrection::CalcPhasedFT() const
|
||||
// CalcRealPhFTDerivative (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculates first derivative of phase-corrected real Fourier spectrum.
|
||||
*
|
||||
* <p>Computes the finite difference derivative: dF/dω ≈ F(i+1) - F(i)
|
||||
* for all interior points. Boundary points are set to 1.0.
|
||||
*
|
||||
* <p>The derivative is used in the entropy calculation, where smooth
|
||||
* spectra (small derivatives) have lower entropy and are preferred by
|
||||
* the optimization algorithm.
|
||||
*
|
||||
* <p><b>Purpose:</b> Entropy minimization favors phase corrections that
|
||||
* produce smooth, well-resolved real spectra with minimal oscillations.
|
||||
*
|
||||
* @see Entropy()
|
||||
*/
|
||||
void PFTPhaseCorrection::CalcRealPhFTDerivative() const
|
||||
{
|
||||
@@ -205,7 +319,22 @@ void PFTPhaseCorrection::CalcRealPhFTDerivative() const
|
||||
// Penalty (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculates penalty term for negative real spectrum values.
|
||||
*
|
||||
* <p>Computes: P = γ·Σ[F_re(ω)² for all F_re(ω) < 0]
|
||||
*
|
||||
* <p>The penalty term penalizes negative values in the real Fourier
|
||||
* spectrum, since physically meaningful absorption-mode spectra should
|
||||
* be predominantly positive. The γ parameter controls the relative
|
||||
* importance of this constraint.
|
||||
*
|
||||
* @return Weighted penalty value (γ×sum of squared negative amplitudes)
|
||||
*
|
||||
* <p><b>Note:</b> Only bins in range [fMinBin, fMaxBin) are considered,
|
||||
* allowing focus on signal-containing regions.
|
||||
*
|
||||
* @see SetGamma()
|
||||
* @see Entropy()
|
||||
*/
|
||||
Double_t PFTPhaseCorrection::Penalty() const
|
||||
{
|
||||
@@ -223,7 +352,26 @@ Double_t PFTPhaseCorrection::Penalty() const
|
||||
// Entropy (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculates Shannon entropy of the real spectrum derivative.
|
||||
*
|
||||
* <p>Computes: S = -Σ[p_i·ln(p_i)] where p_i = |dF/dω|_i / Σ|dF/dω|
|
||||
*
|
||||
* <p>This entropy measure quantifies the "smoothness" of the real
|
||||
* Fourier spectrum:
|
||||
* - <b>Low entropy:</b> Concentrated, smooth spectrum (desired)
|
||||
* - <b>High entropy:</b> Dispersed, noisy spectrum (undesired)
|
||||
*
|
||||
* <p><b>Physical interpretation:</b> Correct phase alignment produces
|
||||
* sharp, well-defined peaks with smooth baselines, resulting in
|
||||
* concentrated derivatives and low entropy.
|
||||
*
|
||||
* @return Shannon entropy of normalized derivative distribution
|
||||
*
|
||||
* <p><b>Note:</b> Small values (< 10⁻¹⁵) are skipped to avoid
|
||||
* numerical issues with log(0).
|
||||
*
|
||||
* @see CalcRealPhFTDerivative()
|
||||
* @see Penalty()
|
||||
*/
|
||||
Double_t PFTPhaseCorrection::Entropy() const
|
||||
{
|
||||
@@ -250,7 +398,29 @@ Double_t PFTPhaseCorrection::Entropy() const
|
||||
// operator() (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Objective function for Minuit2 minimization (FCNBase interface).
|
||||
*
|
||||
* <p>Evaluates the combined entropy-penalty functional:
|
||||
* f(c₀, c₁) = S + γ·P
|
||||
* where:
|
||||
* - S = entropy of phase-corrected real spectrum derivative
|
||||
* - P = penalty for negative values in real spectrum
|
||||
* - γ = balancing parameter (fGamma)
|
||||
*
|
||||
* @param par Parameter vector: [0]=c₀ (constant phase), [1]=c₁ (linear phase)
|
||||
* @return Combined functional value to be minimized
|
||||
*
|
||||
* <p><b>Algorithm flow:</b>
|
||||
* 1. Apply phase correction with parameters par
|
||||
* 2. Calculate phase-corrected Fourier transform
|
||||
* 3. Compute spectrum derivative
|
||||
* 4. Return entropy + penalty
|
||||
*
|
||||
* <p>Called repeatedly by Minuit2 during optimization.
|
||||
*
|
||||
* @see Entropy()
|
||||
* @see Penalty()
|
||||
* @see Minimize()
|
||||
*/
|
||||
double PFTPhaseCorrection::operator()(const std::vector<double> &par) const
|
||||
{
|
||||
@@ -271,15 +441,43 @@ double PFTPhaseCorrection::operator()(const std::vector<double> &par) const
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor.
|
||||
* <p>Constructor for Fourier transform engine.
|
||||
*
|
||||
* \param data data histogram
|
||||
* \param unitTag tag telling in which units the Fourier transform shall be represented. Possible tags are:
|
||||
* FOURIER_UNIT_GAUSS, FOURIER_UNIT_TESLA, FOURIER_UNIT_FREQ, FOURIER_UNIT_CYCLES
|
||||
* \param startTime start time of the data time window
|
||||
* \param endTime end time of the data time window
|
||||
* \param dcCorrected if true, removed DC offset from signal before Fourier transformation, otherwise not
|
||||
* \param zeroPaddingPower if set to values > 0, there will be zero padding up to 2^zeroPaddingPower
|
||||
* <p>Creates a PFourier object configured to transform μSR time-domain
|
||||
* data to frequency/field domain. The constructor validates inputs,
|
||||
* allocates FFTW resources, and prepares for FFT computation.
|
||||
*
|
||||
* @param data TH1F histogram containing time-domain μSR signal.
|
||||
* X-axis: time in microseconds, Y-axis: asymmetry or counts.
|
||||
* @param unitTag Output units for frequency axis:
|
||||
* - FOURIER_UNIT_GAUSS (1): Magnetic field in Gauss
|
||||
* - FOURIER_UNIT_TESLA (2): Magnetic field in Tesla
|
||||
* - FOURIER_UNIT_FREQ (3): Frequency in MHz
|
||||
* - FOURIER_UNIT_CYCLES (4): Angular frequency in Mc/s (Mrad/s)
|
||||
* @param startTime Start of transform window in μs (0.0 = from t₀). Default: 0.0
|
||||
* @param endTime End of transform window in μs (0.0 = to end). Default: 0.0
|
||||
* @param dcCorrected If true, remove DC offset before FFT to eliminate
|
||||
* zero-frequency artifact. Default: false
|
||||
* @param zeroPaddingPower Zero-pad to 2^N points where N=zeroPaddingPower.
|
||||
* Value 0 disables padding. Padding improves frequency
|
||||
* interpolation but doesn't add information. Default: 0
|
||||
*
|
||||
* <p><b>Unit conversions (using γ_μ/2π = 0.01355 MHz/G):</b>
|
||||
* - Gauss: B(G) = ω(MHz) / 0.01355
|
||||
* - Tesla: B(T) = ω(MHz) / 135.54
|
||||
*
|
||||
* <p><b>Example usage:</b>
|
||||
* @code
|
||||
* TH1F *timeHisto = ...; // μSR time spectrum
|
||||
* PFourier ft(timeHisto, FOURIER_UNIT_GAUSS, 0.1, 10.0, true, 12);
|
||||
* ft.Transform(F_APODIZATION_WEAK);
|
||||
* TH1F *powerSpec = ft.GetPowerFourier();
|
||||
* @endcode
|
||||
*
|
||||
* <p>After construction, check IsValid() before calling Transform().
|
||||
*
|
||||
* @see Transform()
|
||||
* @see IsValid()
|
||||
*/
|
||||
PFourier::PFourier(TH1F *data, Int_t unitTag, Double_t startTime, Double_t endTime, Bool_t dcCorrected, UInt_t zeroPaddingPower) :
|
||||
fData(data), fUnitTag(unitTag), fStartTime(startTime), fEndTime(endTime),
|
||||
@@ -372,7 +570,16 @@ PFourier::PFourier(TH1F *data, Int_t unitTag, Double_t startTime, Double_t endTi
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor
|
||||
* <p>Destructor - cleans up FFTW resources.
|
||||
*
|
||||
* <p>Releases all FFTW-allocated memory and destroys the FFT plan.
|
||||
* Proper cleanup is essential to avoid memory leaks, as FFTW uses
|
||||
* special aligned memory allocation.
|
||||
*
|
||||
* <p><b>Resources freed:</b>
|
||||
* - fFFTwPlan: FFTW execution plan
|
||||
* - fIn: Input array (time-domain data)
|
||||
* - fOut: Output array (frequency-domain data)
|
||||
*/
|
||||
PFourier::~PFourier()
|
||||
{
|
||||
@@ -390,10 +597,37 @@ PFourier::~PFourier()
|
||||
// Transform (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Carries out the Fourier transform. It is assumed that fStartTime is the time zero
|
||||
* for the Fourier frame. Hence if fStartTime != 0.0 the phase shift will be corrected.
|
||||
* <p>Executes the Fourier transform with optional apodization.
|
||||
*
|
||||
* \param apodizationTag 0=no apod., 1=weak apod., 2=medium apod., 3=strong apod.
|
||||
* <p>This is the main workhorse method that performs the complete FFT
|
||||
* pipeline:
|
||||
* 1. Prepare input data (DC correction, zero padding)
|
||||
* 2. Apply apodization window if requested
|
||||
* 3. Execute FFTW plan (compute FFT)
|
||||
* 4. Correct phase for non-zero start time
|
||||
*
|
||||
* <p><b>Phase correction:</b> If fStartTime ≠ 0, applies phase shift
|
||||
* e^(i·ω·t₀) to account for the time-zero offset. This ensures proper
|
||||
* phase relationships in the frequency spectrum.
|
||||
*
|
||||
* <p><b>Apodization:</b> Window functions reduce spectral leakage
|
||||
* (Gibbs phenomenon) at the cost of slight peak broadening:
|
||||
* - NONE: Best amplitude accuracy, worst leakage
|
||||
* - WEAK: Minimal smoothing
|
||||
* - MEDIUM: Balanced (recommended for most cases)
|
||||
* - STRONG: Maximum leakage suppression
|
||||
*
|
||||
* @param apodizationTag Window function strength:
|
||||
* - 0 or F_APODIZATION_NONE: No windowing
|
||||
* - 1 or F_APODIZATION_WEAK: Gentle taper
|
||||
* - 2 or F_APODIZATION_MEDIUM: Moderate taper
|
||||
* - 3 or F_APODIZATION_STRONG: Heavy taper
|
||||
*
|
||||
* <p>After calling Transform(), retrieve results using:
|
||||
* GetRealFourier(), GetImaginaryFourier(), GetPowerFourier(), GetPhaseFourier()
|
||||
*
|
||||
* @see PrepareFFTwInputData()
|
||||
* @see GetPowerFourier()
|
||||
*/
|
||||
void PFourier::Transform(UInt_t apodizationTag)
|
||||
{
|
||||
@@ -428,7 +662,25 @@ void PFourier::Transform(UInt_t apodizationTag)
|
||||
// GetMaxFreq (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>returns the maximal frequency in units choosen, i.e. Gauss, Tesla, MHz, Mc/s
|
||||
* <p>Returns the maximum frequency (Nyquist frequency) of the spectrum.
|
||||
*
|
||||
* <p>The Nyquist frequency is the highest frequency that can be
|
||||
* unambiguously represented given the time resolution:
|
||||
* f_Nyquist = 1 / (2·Δt)
|
||||
*
|
||||
* <p>Higher frequencies are aliased back into the [0, f_Nyquist] range,
|
||||
* so the useful spectrum extends from 0 to f_Nyquist.
|
||||
*
|
||||
* @return Maximum frequency in units specified by fUnitTag:
|
||||
* - Gauss (if FOURIER_UNIT_GAUSS)
|
||||
* - Tesla (if FOURIER_UNIT_TESLA)
|
||||
* - MHz (if FOURIER_UNIT_FREQ)
|
||||
* - Mc/s (if FOURIER_UNIT_CYCLES)
|
||||
*
|
||||
* <p><b>Example:</b> For time resolution Δt = 0.01 μs:
|
||||
* f_Nyquist = 1/(2×0.01) = 50 MHz ≈ 3690 Gauss
|
||||
*
|
||||
* @see GetResolution()
|
||||
*/
|
||||
Double_t PFourier::GetMaxFreq()
|
||||
{
|
||||
@@ -445,9 +697,36 @@ Double_t PFourier::GetMaxFreq()
|
||||
// GetRealFourier (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>returns the real part Fourier as a histogram.
|
||||
* <p>Returns real part of Fourier transform as ROOT histogram.
|
||||
*
|
||||
* \param scale normalisation factor
|
||||
* <p>The real component represents the in-phase (cosine) projection
|
||||
* of the signal. Without phase correction, both positive and negative
|
||||
* values typically appear due to arbitrary phase offsets.
|
||||
*
|
||||
* <p><b>Interpretation:</b>
|
||||
* - Phase-corrected: Absorption-mode spectrum (predominantly positive)
|
||||
* - Uncorrected: Mixed-phase spectrum (positive + negative regions)
|
||||
*
|
||||
* <p>Histogram covers [0, f_Nyquist] with N/2 bins where N is the
|
||||
* FFT size (including zero padding if applied).
|
||||
*
|
||||
* @param scale Multiplication factor applied to all amplitudes.
|
||||
* Use for normalization or unit conversion. Default: 1.0
|
||||
*
|
||||
* @return Pointer to newly allocated TH1F histogram. <b>Caller owns
|
||||
* the histogram and must delete it.</b> Returns nullptr on error.
|
||||
*
|
||||
* <p><b>Example:</b>
|
||||
* @code
|
||||
* ft.Transform(F_APODIZATION_WEAK);
|
||||
* TH1F *realSpec = ft.GetRealFourier(1.0);
|
||||
* realSpec->Draw();
|
||||
* // ... use histogram ...
|
||||
* delete realSpec;
|
||||
* @endcode
|
||||
*
|
||||
* @see GetImaginaryFourier()
|
||||
* @see GetPhaseOptRealFourier()
|
||||
*/
|
||||
TH1F* PFourier::GetRealFourier(const Double_t scale)
|
||||
{
|
||||
@@ -486,16 +765,54 @@ TH1F* PFourier::GetRealFourier(const Double_t scale)
|
||||
// GetPhaseOptRealFourier (public, static)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>returns the phase corrected real Fourier transform.
|
||||
* <p>Returns phase-optimized real Fourier spectrum (static method).
|
||||
*
|
||||
* \return the TH1F histo of the phase 'optimzed' real Fourier transform.
|
||||
* <p>This static method performs automatic phase correction on a complex
|
||||
* Fourier spectrum to maximize the real component (absorption mode) while
|
||||
* minimizing the imaginary component. The algorithm finds optimal phase
|
||||
* parameters φ(ω) = c₀ + c₁·ω that produce the cleanest real spectrum.
|
||||
*
|
||||
* \param re real part Fourier histogram
|
||||
* \param im imaginary part Fourier histogram
|
||||
* \param phase return value of the optimal phase dispersion phase[0]+phase[1]*i/N
|
||||
* \param scale normalisation factor
|
||||
* \param min minimal freq / field from which to optimise. Given in the choosen unit.
|
||||
* \param max maximal freq / field up to which to optimise. Given in the choosen unit.
|
||||
* <p><b>Why phase correction?</b> Raw FFT produces mixed-phase spectra
|
||||
* with arbitrary phase offsets due to:
|
||||
* - Uncertain time-zero (t₀) determination
|
||||
* - Detector timing offsets
|
||||
* - Signal propagation delays
|
||||
*
|
||||
* <p><b>Algorithm:</b>
|
||||
* 1. Extract Re/Im data in specified frequency range [min, max]
|
||||
* 2. Use PFTPhaseCorrection to minimize entropy+penalty functional
|
||||
* 3. Apply optimal phase rotation to entire spectrum
|
||||
* 4. Return phase-corrected real part
|
||||
*
|
||||
* <p><b>Optimization range [min, max]:</b> Restrict to signal-containing
|
||||
* regions for best results. Including noisy baseline degrades optimization.
|
||||
*
|
||||
* @param re Real part of Fourier transform (TH1F histogram)
|
||||
* @param im Imaginary part of Fourier transform (TH1F histogram)
|
||||
* @param phase Output parameter: phase[0]=c₀, phase[1]=c₁ (vector resized to 2)
|
||||
* @param scale Amplitude scaling factor. Default: 1.0
|
||||
* @param min Minimum frequency/field for optimization window.
|
||||
* Use -1.0 to include all frequencies. Default: -1.0
|
||||
* @param max Maximum frequency/field for optimization window.
|
||||
* Use -1.0 to include all frequencies. Default: -1.0
|
||||
*
|
||||
* @return Pointer to newly allocated phase-corrected TH1F histogram.
|
||||
* <b>Caller owns and must delete.</b> Returns nullptr on error.
|
||||
*
|
||||
* <p><b>Example:</b>
|
||||
* @code
|
||||
* TH1F *real = ft.GetRealFourier();
|
||||
* TH1F *imag = ft.GetImaginaryFourier();
|
||||
* std::vector<Double_t> phaseParams;
|
||||
* TH1F *phCorrected = PFourier::GetPhaseOptRealFourier(real, imag, phaseParams, 1.0, 5.0, 50.0);
|
||||
* std::cout << "Phase: " << phaseParams[0] << " + " << phaseParams[1] << "*w" << std::endl;
|
||||
* phCorrected->Draw();
|
||||
* delete real; delete imag; delete phCorrected;
|
||||
* @endcode
|
||||
*
|
||||
* @see PFTPhaseCorrection
|
||||
* @see GetRealFourier()
|
||||
* @see GetImaginaryFourier()
|
||||
*/
|
||||
TH1F* PFourier::GetPhaseOptRealFourier(const TH1F *re, const TH1F *im, std::vector<Double_t> &phase,
|
||||
const Double_t scale, const Double_t min, const Double_t max)
|
||||
@@ -587,9 +904,29 @@ TH1F* PFourier::GetPhaseOptRealFourier(const TH1F *re, const TH1F *im, std::vect
|
||||
// GetImaginaryFourier (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>returns the imaginary part Fourier as a histogram.
|
||||
* <p>Returns imaginary part of Fourier transform as ROOT histogram.
|
||||
*
|
||||
* \param scale normalisation factor
|
||||
* <p>The imaginary component represents the out-of-phase (sine)
|
||||
* projection of the signal. Ideally zero for perfect phase correction,
|
||||
* but contains signal information when phase is uncorrected.
|
||||
*
|
||||
* <p><b>Uses:</b>
|
||||
* - Phase correction optimization (minimize imaginary component)
|
||||
* - Dispersion-mode spectroscopy
|
||||
* - Computing power spectrum: |F|² = Re² + Im²
|
||||
* - Phase spectrum calculation: φ = atan(Im/Re)
|
||||
*
|
||||
* <p>Histogram covers [0, f_Nyquist] with N/2 bins where N is the
|
||||
* FFT size (including zero padding if applied).
|
||||
*
|
||||
* @param scale Multiplication factor applied to all amplitudes.
|
||||
* Use for normalization or unit conversion. Default: 1.0
|
||||
*
|
||||
* @return Pointer to newly allocated TH1F histogram. <b>Caller owns
|
||||
* the histogram and must delete it.</b> Returns nullptr on error.
|
||||
*
|
||||
* @see GetRealFourier()
|
||||
* @see GetPhaseOptRealFourier()
|
||||
*/
|
||||
TH1F* PFourier::GetImaginaryFourier(const Double_t scale)
|
||||
{
|
||||
@@ -629,9 +966,37 @@ TH1F* PFourier::GetImaginaryFourier(const Double_t scale)
|
||||
// GetPowerFourier (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>returns the Fourier power spectrum as a histogram.
|
||||
* <p>Returns power spectrum |F(ω)| as ROOT histogram.
|
||||
*
|
||||
* \param scale normalisation factor
|
||||
* <p>The power spectrum shows signal magnitude at each frequency,
|
||||
* computed as: |F(ω)| = √(Re² + Im²)
|
||||
*
|
||||
* <p><b>Advantages:</b>
|
||||
* - Always positive (easier interpretation)
|
||||
* - Phase-independent (no phase correction needed)
|
||||
* - Directly shows signal strength vs. frequency
|
||||
* - Ideal for identifying all frequency components
|
||||
*
|
||||
* <p><b>Applications:</b>
|
||||
* - Quick survey of frequency content
|
||||
* - Field distribution analysis in superconductors
|
||||
* - Multiple muon site identification
|
||||
* - TF-μSR field measurements
|
||||
*
|
||||
* <p>Histogram covers [0, f_Nyquist] with N/2 bins where N is the
|
||||
* FFT size (including zero padding if applied).
|
||||
*
|
||||
* @param scale Multiplication factor applied to all amplitudes.
|
||||
* Use for normalization or unit conversion. Default: 1.0
|
||||
*
|
||||
* @return Pointer to newly allocated TH1F histogram. <b>Caller owns
|
||||
* the histogram and must delete it.</b> Returns nullptr on error.
|
||||
*
|
||||
* <p><b>Note:</b> This returns the amplitude |F|, not the power |F|².
|
||||
* For power values, square the histogram contents.
|
||||
*
|
||||
* @see GetRealFourier()
|
||||
* @see GetPhaseFourier()
|
||||
*/
|
||||
TH1F* PFourier::GetPowerFourier(const Double_t scale)
|
||||
{
|
||||
@@ -671,9 +1036,39 @@ TH1F* PFourier::GetPowerFourier(const Double_t scale)
|
||||
// GetPhaseFourier (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>returns the Fourier phase spectrum as a histogram.
|
||||
* <p>Returns phase spectrum φ(ω) = arg(F) as ROOT histogram.
|
||||
*
|
||||
* \param scale normalisation factor
|
||||
* <p>The phase spectrum shows the phase angle of the complex Fourier
|
||||
* transform at each frequency: φ(ω) = atan2(Im, Re)
|
||||
*
|
||||
* <p><b>Range:</b> Phase values are in [-π, +π] radians, with proper
|
||||
* quadrant handling using the two-argument arctangent.
|
||||
*
|
||||
* <p><b>Interpretation:</b>
|
||||
* - Constant phase: All frequencies in phase (simple exponential decay)
|
||||
* - Linear phase: Time-zero offset (shift theorem)
|
||||
* - Quadratic phase: Dispersion or chirp
|
||||
* - Random phase: Noise
|
||||
*
|
||||
* <p><b>Applications:</b>
|
||||
* - Diagnosing time-zero problems
|
||||
* - Verifying phase correction quality
|
||||
* - Identifying signal vs. noise regions
|
||||
*
|
||||
* <p>Histogram covers [0, f_Nyquist] with N/2 bins where N is the
|
||||
* FFT size (including zero padding if applied).
|
||||
*
|
||||
* @param scale Multiplication factor applied to phase values.
|
||||
* Typically 1.0 (radians) or 180/π (degrees). Default: 1.0
|
||||
*
|
||||
* @return Pointer to newly allocated TH1F histogram. <b>Caller owns
|
||||
* the histogram and must delete it.</b> Returns nullptr on error.
|
||||
*
|
||||
* <p><b>Note:</b> Phase is undefined where amplitude is zero. In practice,
|
||||
* phase values in noise regions are meaningless.
|
||||
*
|
||||
* @see GetRealFourier()
|
||||
* @see GetImaginaryFourier()
|
||||
*/
|
||||
TH1F* PFourier::GetPhaseFourier(const Double_t scale)
|
||||
{
|
||||
@@ -730,11 +1125,32 @@ TH1F* PFourier::GetPhaseFourier(const Double_t scale)
|
||||
// PrepareFFTwInputData (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Feeds the Fourier data and apply the apodization.
|
||||
* <p>Prepares time-domain data for FFT with optional DC correction and apodization.
|
||||
*
|
||||
* \param apodizationTag apodization tag. Possible are currently: F_APODIZATION_NONE = no apodization,
|
||||
* F_APODIZATION_WEAK = weak apodization, F_APODIZATION_MEDIUM = intermediate apodization,
|
||||
* F_APODIZATION_STRONG = strong apodization
|
||||
* <p>This method performs essential preprocessing steps:
|
||||
* 1. Locates time-zero bin in the histogram
|
||||
* 2. Extracts data from [fStartTime, fEndTime] window
|
||||
* 3. Removes DC offset (if fDCCorrected=true) for baseline correction
|
||||
* 4. Zero-pads to fNoOfBins (power of 2 for optimal FFT performance)
|
||||
* 5. Applies apodization window to reduce spectral leakage
|
||||
*
|
||||
* <p><b>DC Correction:</b> Subtracts mean value from time signal to
|
||||
* remove constant offset, which would otherwise create a large artifact
|
||||
* at zero frequency.
|
||||
*
|
||||
* <p><b>Zero Padding:</b> Increases frequency resolution by interpolation
|
||||
* without adding information content. Often used for smoother spectra.
|
||||
*
|
||||
* @param apodizationTag Window function strength:
|
||||
* - F_APODIZATION_NONE (1): Rectangular window (no smoothing)
|
||||
* - F_APODIZATION_WEAK (2): Gentle roll-off at edges
|
||||
* - F_APODIZATION_MEDIUM (3): Moderate smoothing
|
||||
* - F_APODIZATION_STRONG (4): Heavy smoothing for maximum leakage suppression
|
||||
*
|
||||
* <p>Result is stored in fIn[] array ready for FFTW execution.
|
||||
*
|
||||
* @see ApodizeData()
|
||||
* @see Transform()
|
||||
*/
|
||||
void PFourier::PrepareFFTwInputData(UInt_t apodizationTag)
|
||||
{
|
||||
@@ -779,11 +1195,33 @@ void PFourier::PrepareFFTwInputData(UInt_t apodizationTag)
|
||||
// ApodizeData (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Carries out the appodization of the data.
|
||||
* <p>Applies apodization (windowing) to time-domain data before FFT.
|
||||
*
|
||||
* \param apodizationTag apodization tag. Possible are currently: F_APODIZATION_NONE = no apodization,
|
||||
* F_APODIZATION_WEAK = weak apodization, F_APODIZATION_MEDIUM = intermediate apodization,
|
||||
* F_APODIZATION_STRONG = strong apodization
|
||||
* <p><b>Purpose:</b> Apodization multiplies the time signal by a smooth
|
||||
* window function that tapers to zero at the edges, reducing the Gibbs
|
||||
* phenomenon (spectral leakage) caused by finite observation windows.
|
||||
*
|
||||
* <p><b>Trade-off:</b>
|
||||
* - <b>Advantage:</b> Sharper, cleaner frequency peaks with less sidelobes
|
||||
* - <b>Disadvantage:</b> Slightly broader main peaks, reduced amplitude accuracy
|
||||
*
|
||||
* <p><b>Window functions:</b> Polynomial windows of the form:
|
||||
* w(t) = Σ c_j·(t/T)^(2j) where t ∈ [0,T]
|
||||
*
|
||||
* <p>Three predefined window strengths with optimized coefficients:
|
||||
* - <b>Weak:</b> Minimal smoothing, preserves amplitude
|
||||
* - <b>Medium:</b> Balanced smoothing for general use
|
||||
* - <b>Strong:</b> Maximum leakage suppression for crowded spectra
|
||||
*
|
||||
* @param apodizationTag Window function type:
|
||||
* - F_APODIZATION_NONE: No windowing (rectangular)
|
||||
* - F_APODIZATION_WEAK: Gentle taper
|
||||
* - F_APODIZATION_MEDIUM: Moderate taper
|
||||
* - F_APODIZATION_STRONG: Heavy taper
|
||||
*
|
||||
* <p>Window is applied in-place to fIn[] array.
|
||||
*
|
||||
* @see PrepareFFTwInputData()
|
||||
*/
|
||||
void PFourier::ApodizeData(Int_t apodizationTag) {
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -50,7 +50,20 @@ ClassImpQ(PFourierCanvas)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* <p>Default constructor - creates uninitialized canvas.
|
||||
*
|
||||
* <p>Initializes all member variables to safe default values. This
|
||||
* constructor produces an invalid canvas (IsValid() returns false).
|
||||
* Use full constructors with Fourier data for functional canvases.
|
||||
*
|
||||
* <p><b>State after construction:</b>
|
||||
* - No timeout, no batch mode
|
||||
* - All view flags disabled
|
||||
* - Empty title and axis labels
|
||||
* - Zero phase offset
|
||||
* - Null GUI pointers
|
||||
*
|
||||
* <p>Primarily used internally or for two-stage initialization patterns.
|
||||
*/
|
||||
PFourierCanvas::PFourierCanvas()
|
||||
{
|
||||
@@ -76,19 +89,39 @@ PFourierCanvas::PFourierCanvas()
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* <p>Full constructor with automatic marker/color generation.
|
||||
*
|
||||
* \param fourier
|
||||
* \param title
|
||||
* \param showAverage
|
||||
* \param fourierPlotOpt
|
||||
* \param fourierXrange
|
||||
* \param phase
|
||||
* \param wtopx
|
||||
* \param wtopy
|
||||
* \param ww
|
||||
* \param wh
|
||||
* \param batch
|
||||
* <p>Creates a complete, functional Fourier canvas ready for display.
|
||||
* Automatically generates random but consistent markers (styles 20-29)
|
||||
* and colors for each dataset based on seeded random numbers.
|
||||
*
|
||||
* <p><b>Initialization sequence:</b>
|
||||
* 1. Store configuration parameters
|
||||
* 2. Generate random markers/colors (reproducible from dataset index)
|
||||
* 3. Create axis titles based on unit type
|
||||
* 4. Set up ROOT plotting style
|
||||
* 5. Generate all Fourier histograms (Re/Im/Pwr/Phase/PhaseOpt)
|
||||
* 6. Create ROOT canvas with menus and pads
|
||||
* 7. Connect signals/slots for interactivity
|
||||
*
|
||||
* @param fourier Vector of PFourier objects (must be already transformed)
|
||||
* @param dataSetTag Dataset group identifiers for averaging
|
||||
* @param title Window title string
|
||||
* @param showAverage Start in all-data averaged view
|
||||
* @param showAveragePerDataSet Start in per-dataset averaged view
|
||||
* @param fourierPlotOpt Initial view mode (FOURIER_PLOT_*)
|
||||
* @param fourierXrange X-axis display range [min, max]
|
||||
* @param phase Initial phase offset in degrees (for Re/Im views)
|
||||
* @param wtopx Canvas window x-position in pixels
|
||||
* @param wtopy Canvas window y-position in pixels
|
||||
* @param ww Canvas width in pixels
|
||||
* @param wh Canvas height in pixels
|
||||
* @param batch If true, suppress GUI (for automated plotting)
|
||||
*
|
||||
* <p>Check IsValid() after construction to verify success.
|
||||
*
|
||||
* @see InitFourierDataSets()
|
||||
* @see InitFourierCanvas()
|
||||
*/
|
||||
PFourierCanvas::PFourierCanvas(std::vector<PFourier*> &fourier, PIntVector dataSetTag, const Char_t* title,
|
||||
const Bool_t showAverage, const Bool_t showAveragePerDataSet,
|
||||
@@ -127,21 +160,45 @@ PFourierCanvas::PFourierCanvas(std::vector<PFourier*> &fourier, PIntVector dataS
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* <p>Full constructor with explicit marker/color specification.
|
||||
*
|
||||
* \param fourier
|
||||
* \param title
|
||||
* \param showAverage
|
||||
* \param fourierPlotOpt
|
||||
* \param fourierXrange
|
||||
* \param phase
|
||||
* \param wtopx
|
||||
* \param wtopy
|
||||
* \param ww
|
||||
* \param wh
|
||||
* \param markerList
|
||||
* \param colorList
|
||||
* \param batch
|
||||
* <p>Creates a complete Fourier canvas with user-defined plot styling.
|
||||
* Provides full control over visual appearance by specifying ROOT marker
|
||||
* styles and color indices for each dataset.
|
||||
*
|
||||
* <p><b>Marker styles:</b> ROOT marker codes (typically 20-34):
|
||||
* - 20: filled circle
|
||||
* - 21: filled square
|
||||
* - 22: filled triangle up
|
||||
* - 23: filled triangle down
|
||||
* - etc.
|
||||
*
|
||||
* <p><b>Colors:</b> ROOT color palette indices or RGB-defined colors
|
||||
* via TColor::GetColor(r,g,b).
|
||||
*
|
||||
* <p><b>Partial lists:</b> If markerList or colorList contain fewer
|
||||
* entries than datasets, remaining entries are auto-generated randomly.
|
||||
*
|
||||
* @param fourier Vector of PFourier objects (must be already transformed)
|
||||
* @param dataSetTag Dataset group identifiers for averaging
|
||||
* @param title Window title string
|
||||
* @param showAverage Start in all-data averaged view
|
||||
* @param showAveragePerDataSet Start in per-dataset averaged view
|
||||
* @param fourierPlotOpt Initial view mode (FOURIER_PLOT_*)
|
||||
* @param fourierXrange X-axis display range [min, max]
|
||||
* @param phase Initial phase offset in degrees (for Re/Im views)
|
||||
* @param wtopx Canvas window x-position in pixels
|
||||
* @param wtopy Canvas window y-position in pixels
|
||||
* @param ww Canvas width in pixels
|
||||
* @param wh Canvas height in pixels
|
||||
* @param markerList ROOT marker style codes for each dataset
|
||||
* @param colorList ROOT color indices for each dataset
|
||||
* @param batch If true, suppress GUI (for automated plotting)
|
||||
*
|
||||
* <p>Check IsValid() after construction to verify success.
|
||||
*
|
||||
* @see InitFourierDataSets()
|
||||
* @see InitFourierCanvas()
|
||||
*/
|
||||
PFourierCanvas::PFourierCanvas(std::vector<PFourier*> &fourier, PIntVector dataSetTag, const Char_t* title,
|
||||
const Bool_t showAverage, const Bool_t showAveragePerDataSet,
|
||||
@@ -185,9 +242,25 @@ PFourierCanvas::PFourierCanvas(std::vector<PFourier*> &fourier, PIntVector dataS
|
||||
// Done (SIGNAL)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Signal emitted that the user wants to terminate the application.
|
||||
* <p>Emits Done signal to notify parent application of canvas closure.
|
||||
*
|
||||
* \param status Status info
|
||||
* <p>This ROOT signal mechanism allows parent objects to connect cleanup
|
||||
* handlers or application flow logic. Typically called when:
|
||||
* - User closes canvas window
|
||||
* - User presses 'q' to quit
|
||||
* - Timeout expires
|
||||
* - SaveGraphicsAndQuit() completes
|
||||
*
|
||||
* @param status Exit status: 0=normal, non-zero=error/abort
|
||||
*
|
||||
* <p><b>Example connection:</b>
|
||||
* @code
|
||||
* PFourierCanvas *canvas = new PFourierCanvas(...);
|
||||
* QObject::connect(canvas, SIGNAL(Done(Int_t)), app, SLOT(Quit()));
|
||||
* @endcode
|
||||
*
|
||||
* @see LastCanvasClosed()
|
||||
* @see SaveGraphicsAndQuit()
|
||||
*/
|
||||
void PFourierCanvas::Done(Int_t status)
|
||||
{
|
||||
@@ -198,19 +271,37 @@ void PFourierCanvas::Done(Int_t status)
|
||||
// HandleCmdKey (SLOT)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Filters keyboard events, and if they are a command key (see below) carries out the
|
||||
* necessary actions.
|
||||
* <p>Currently implemented command keys:
|
||||
* - 'q' quit musrview
|
||||
* - 'u' unzoom to the original plot range given in the msr-file.
|
||||
* - 'a' toggle between average view and single Fourier histo view.
|
||||
* - '+' increment the phase (real/imaginary Fourier). The phase step is defined in the musrfit_startup.xml
|
||||
* - '-' decrement the phase (real/imaginary Fourier). The phase step is defined in the musrfit_startup.xml
|
||||
* <p>Processes keyboard shortcuts for canvas control.
|
||||
*
|
||||
* \param event event type
|
||||
* \param x character key
|
||||
* \param y not used
|
||||
* \param selected not used
|
||||
* <p>This slot receives keyboard events from ROOT and dispatches
|
||||
* appropriate actions. Ignored in batch mode.
|
||||
*
|
||||
* <p><b>Keyboard shortcuts:</b>
|
||||
* - <b>'q':</b> Quit - emits Done(0) signal to close canvas
|
||||
* - <b>'u':</b> Unzoom - reset view to initial X/Y range
|
||||
* - <b>'a':</b> Toggle all-data average view on/off
|
||||
* - <b>'d':</b> Toggle per-dataset average view on/off
|
||||
* - <b>'c':</b> Toggle crosshair cursor on/off
|
||||
* - <b>'+':</b> Increment phase by 5° (Re/Im views only)
|
||||
* - <b>'-':</b> Decrement phase by 5° (Re/Im views only)
|
||||
*
|
||||
* <p><b>Phase adjustment:</b> Only affects Real and Imaginary Fourier
|
||||
* views. Phase value is displayed as text overlay on canvas.
|
||||
*
|
||||
* <p><b>Average toggling:</b> 'a' and 'd' are mutually exclusive.
|
||||
* Activating one deactivates the other. Switching triggers histogram
|
||||
* recomputation via HandleAverage().
|
||||
*
|
||||
* @param event ROOT event type (must be kKeyPress to process)
|
||||
* @param x ASCII code of pressed key
|
||||
* @param y Mouse y-coordinate (unused)
|
||||
* @param selected Object under cursor (unused)
|
||||
*
|
||||
* @see IncrementFourierPhase()
|
||||
* @see DecrementFourierPhase()
|
||||
* @see HandleAverage()
|
||||
* @see PlotFourier()
|
||||
* @see PlotAverage()
|
||||
*/
|
||||
void PFourierCanvas::HandleCmdKey(Int_t event, Int_t x, Int_t y, TObject *selected)
|
||||
{
|
||||
@@ -282,9 +373,33 @@ void PFourierCanvas::HandleCmdKey(Int_t event, Int_t x, Int_t y, TObject *select
|
||||
// HandleMenuPopup (SLOT)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Handles the MusrFT menu.
|
||||
* <p>Processes menu selection events from the MusrFT menu bar.
|
||||
*
|
||||
* \param id identification key of the selected menu
|
||||
* <p>Handles all menu item clicks including:
|
||||
* - Fourier view mode selection (Real/Imag/Power/Phase/etc.)
|
||||
* - Averaging mode toggles (All/Per-dataset/Off)
|
||||
* - Phase adjustment (±5°)
|
||||
* - Data export
|
||||
*
|
||||
* <p><b>Menu structure:</b>
|
||||
* - <b>MusrFT/Fourier:</b> View mode submenu
|
||||
* - Real, Imaginary, Real+Imag, Power, Phase, Phase-Optimized
|
||||
* - Phase +/- adjustments
|
||||
* - <b>MusrFT/Average:</b> All-data average toggle
|
||||
* - <b>MusrFT/Average Per Data Set:</b> Per-dataset average toggle
|
||||
* - <b>MusrFT/Export Data:</b> Save to ASCII file
|
||||
*
|
||||
* <p>View changes trigger canvas redraw with new histogram type.
|
||||
* Averaging changes recompute histograms via HandleAverage().
|
||||
*
|
||||
* <p>Ignored in batch mode.
|
||||
*
|
||||
* @param id Menu item identifier (P_MENU_ID_* constants)
|
||||
*
|
||||
* @see HandleAverage()
|
||||
* @see PlotFourier()
|
||||
* @see PlotAverage()
|
||||
* @see ExportData()
|
||||
*/
|
||||
void PFourierCanvas::HandleMenuPopup(Int_t id)
|
||||
{
|
||||
@@ -473,9 +588,26 @@ void PFourierCanvas::UpdateInfoPad()
|
||||
// SetTimeout (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>sets the timeout after which the program shall terminate.
|
||||
* <p>Configures automatic canvas closure after specified timeout.
|
||||
*
|
||||
* \param timeout after which the done signal shall be emitted. Given in seconds
|
||||
* <p>Creates and starts a ROOT TTimer that emits Done() signal after
|
||||
* the timeout expires. Useful for:
|
||||
* - Batch processing with timed display
|
||||
* - Automated testing and screenshot capture
|
||||
* - Slideshow-style data review
|
||||
*
|
||||
* <p>If timeout ≤ 0, no timer is created (infinite display time).
|
||||
*
|
||||
* <p><b>Timer behavior:</b> Single-shot (kTRUE flag), fires once then stops.
|
||||
*
|
||||
* @param timeout Duration in <b>seconds</b> before auto-close (≤0 = disabled)
|
||||
*
|
||||
* <p><b>Example:</b>
|
||||
* @code
|
||||
* canvas->SetTimeout(30); // Close after 30 seconds
|
||||
* @endcode
|
||||
*
|
||||
* @see Done()
|
||||
*/
|
||||
void PFourierCanvas::SetTimeout(Int_t timeout)
|
||||
{
|
||||
@@ -495,9 +627,32 @@ void PFourierCanvas::SetTimeout(Int_t timeout)
|
||||
// SaveGraphicsAndQuit
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Will save the canvas as graphics output. Needed in the batch mode of musrview.
|
||||
* <p>Exports canvas to graphics file and terminates.
|
||||
*
|
||||
* \param fileName file name under which the canvas shall be saved.
|
||||
* <p>Saves current canvas view to image file, then emits Done(0) signal
|
||||
* to trigger cleanup. Primary use: batch mode automated plotting.
|
||||
*
|
||||
* <p><b>Supported formats</b> (determined by file extension):
|
||||
* - <b>.pdf:</b> Vector PDF (best for publications)
|
||||
* - <b>.eps:</b> Encapsulated PostScript (vector)
|
||||
* - <b>.png:</b> Raster PNG (good for web/presentations)
|
||||
* - <b>.jpg/.jpeg:</b> Raster JPEG (compressed)
|
||||
* - <b>.svg:</b> Scalable Vector Graphics
|
||||
* - <b>.root:</b> ROOT file (preserves interactive features)
|
||||
* - <b>.C:</b> ROOT macro (for programmatic recreation)
|
||||
*
|
||||
* <p>ROOT's TCanvas::SaveAs() handles format detection automatically.
|
||||
*
|
||||
* @param fileName Output file path with extension indicating format
|
||||
*
|
||||
* <p><b>Batch mode workflow:</b>
|
||||
* @code
|
||||
* PFourierCanvas *canvas = new PFourierCanvas(..., batch=true);
|
||||
* canvas->SaveGraphicsAndQuit("output.pdf");
|
||||
* // Canvas closes automatically after saving
|
||||
* @endcode
|
||||
*
|
||||
* @see Done()
|
||||
*/
|
||||
void PFourierCanvas::SaveGraphicsAndQuit(const Char_t *fileName)
|
||||
{
|
||||
@@ -512,7 +667,44 @@ void PFourierCanvas::SaveGraphicsAndQuit(const Char_t *fileName)
|
||||
// ExportData
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Exports the currently displayed Fourier data set in ascii column format.
|
||||
* <p>Exports currently displayed Fourier spectrum to ASCII data file.
|
||||
*
|
||||
* <p>Writes frequency/field values and corresponding spectrum amplitudes
|
||||
* in columnar text format suitable for:
|
||||
* - External plotting tools (Origin, MATLAB, Gnuplot, etc.)
|
||||
* - Statistical analysis packages (R, Python, etc.)
|
||||
* - Spreadsheet applications (Excel, LibreOffice)
|
||||
* - Archival data storage
|
||||
*
|
||||
* <p><b>File format:</b>
|
||||
* - Header: Column labels (X-axis, dataset names)
|
||||
* - Data: Space-separated columns
|
||||
* - Column 1: Frequency/field values
|
||||
* - Columns 2+: Spectrum values for each dataset
|
||||
*
|
||||
* <p><b>Exported spectrum:</b> Depends on current view mode:
|
||||
* - Real view → Real parts
|
||||
* - Imaginary view → Imaginary parts
|
||||
* - Power view → Power spectra
|
||||
* - Phase view → Phase spectra
|
||||
* - Phase-optimized → Phase-corrected real parts
|
||||
* - Real+Imag view → Both real and imaginary columns
|
||||
*
|
||||
* <p><b>Averaging:</b> If average mode active, exports averaged data
|
||||
* instead of individual runs.
|
||||
*
|
||||
* <p><b>X-range:</b> Only exports visible X-axis range (honors zoom).
|
||||
*
|
||||
* @param pathFileName Output file path (typically .dat extension).
|
||||
* Must not be nullptr.
|
||||
*
|
||||
* <p><b>Example output format:</b>
|
||||
* @code
|
||||
* # Field(G) Run1_Real Run2_Real Run3_Real
|
||||
* 100.5 0.234 0.221 0.245
|
||||
* 101.0 0.198 0.187 0.203
|
||||
* ...
|
||||
* @endcode
|
||||
*/
|
||||
void PFourierCanvas::ExportData(const Char_t *pathFileName)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -30,8 +30,12 @@
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
|
||||
#include "PFunctionHandler.h"
|
||||
|
||||
namespace x3 = boost::spirit::x3;
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Constructor
|
||||
//-------------------------------------------------------------
|
||||
@@ -67,7 +71,6 @@ PFunctionHandler::~PFunctionHandler()
|
||||
Bool_t PFunctionHandler::DoParse()
|
||||
{
|
||||
Bool_t success = true;
|
||||
PFunctionGrammar function;
|
||||
TString line;
|
||||
|
||||
// feed the function block into the parser. Start with i=1, since i=0 is FUNCTIONS
|
||||
@@ -89,14 +92,32 @@ Bool_t PFunctionHandler::DoParse()
|
||||
}
|
||||
line.ToUpper();
|
||||
|
||||
// do parsing
|
||||
tree_parse_info<> info = ast_parse(line.Data(), function, space_p);
|
||||
// do parsing with X3
|
||||
musrfit::ast::assignment assignment;
|
||||
std::string str(line.Data());
|
||||
auto iter = str.begin();
|
||||
auto end = str.end();
|
||||
|
||||
if (info.full) { // parsing successful
|
||||
PFunction func(info); // generate an evaluation function object based on the AST tree
|
||||
fFuncs.push_back(func); // feeds it to the functions vector
|
||||
} else {
|
||||
// Get the X3 grammar
|
||||
auto const& grammar = musrfit::function_grammar();
|
||||
|
||||
try {
|
||||
bool parseSuccess = x3::phrase_parse(iter, end, grammar, x3::space, assignment);
|
||||
|
||||
if (parseSuccess && iter == end) { // parsing successful
|
||||
PFunction func(assignment); // generate an evaluation function object based on the AST
|
||||
fFuncs.push_back(func); // feeds it to the functions vector
|
||||
} else {
|
||||
std::cerr << std::endl << "**ERROR**: FUNCTIONS parse failed in line " << fLines[i].fLineNo << std::endl;
|
||||
if (iter != end) {
|
||||
std::cerr << "**ERROR**: Stopped at: " << std::string(iter, end) << std::endl;
|
||||
}
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
} catch (x3::expectation_failure<std::string::iterator> const& e) {
|
||||
std::cerr << std::endl << "**ERROR**: FUNCTIONS parse failed in line " << fLines[i].fLineNo << std::endl;
|
||||
std::cerr << "**ERROR**: Expected: " << e.which() << std::endl;
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -29,10 +29,42 @@
|
||||
|
||||
#include "PMsgBox.h"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* \brief Constructor that creates and displays the message box GUI.
|
||||
*
|
||||
* This constructor performs the following steps:
|
||||
* 1. Creates a scrollable list box widget
|
||||
* 2. Parses the error message string by splitting at newline characters
|
||||
* 3. Populates the list box with individual message lines
|
||||
* 4. Creates an Exit button with callback to DoExit()
|
||||
* 5. Configures layout and displays the window
|
||||
*
|
||||
* The message parsing algorithm:
|
||||
* - Adds an initial empty line
|
||||
* - Splits the input string at each '\n' character
|
||||
* - Each substring becomes a separate list box entry
|
||||
* - Handles multi-line messages gracefully
|
||||
*
|
||||
* GUI Layout:
|
||||
* - List box: 600x200 pixels, expandable, with 5-pixel margins
|
||||
* - Button frame: Fixed width (150px), contains Exit button
|
||||
* - Window title: "Error Message"
|
||||
*
|
||||
* \param errMsg Multi-line error message string with '\n' separators
|
||||
* \param p Parent window pointer (typically gClient->GetRoot())
|
||||
* \param w Initial window width in pixels
|
||||
* \param h Initial window height in pixels
|
||||
*
|
||||
* \note The window is automatically mapped (displayed) after construction
|
||||
* \note The list box ID is set to 89 (ROOT widget identifier)
|
||||
*/
|
||||
PMsgBox::PMsgBox(const std::string errMsg, const TGWindow *p, UInt_t w, UInt_t h) : TGMainFrame(p, w, h)
|
||||
{
|
||||
fListBox = new TGListBox(this, 89);
|
||||
|
||||
|
||||
// feed list box with errMsg
|
||||
size_t start = 0;
|
||||
size_t end = errMsg.find("\n");
|
||||
@@ -45,7 +77,7 @@ PMsgBox::PMsgBox(const std::string errMsg, const TGWindow *p, UInt_t w, UInt_t h
|
||||
end = errMsg.find("\n", start);
|
||||
fListBox->AddEntry(tok.c_str(), i++);
|
||||
}
|
||||
|
||||
|
||||
fListBox->Resize(600, 200);
|
||||
AddFrame(fListBox, new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX | kLHintsExpandY, 5, 5, 5, 5));
|
||||
|
||||
@@ -67,11 +99,45 @@ PMsgBox::PMsgBox(const std::string errMsg, const TGWindow *p, UInt_t w, UInt_t h
|
||||
MapWindow();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* \brief Destructor that cleans up the message box resources.
|
||||
*
|
||||
* The ROOT framework automatically handles cleanup of GUI components
|
||||
* (list box, buttons, frames) through the TGMainFrame destructor chain,
|
||||
* so no explicit cleanup is required here.
|
||||
*
|
||||
* \note GUI widgets are managed by ROOT and are automatically deleted
|
||||
* when the main frame is destroyed
|
||||
*/
|
||||
PMsgBox::~PMsgBox()
|
||||
{
|
||||
// nothing to be done here?
|
||||
// nothing to be done here - ROOT handles GUI cleanup automatically
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// DoExit
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* \brief Exit button callback that terminates the application.
|
||||
*
|
||||
* This method is invoked when the user clicks the Exit button.
|
||||
* It terminates the entire ROOT application with exit code 0,
|
||||
* which causes a clean shutdown of the program.
|
||||
*
|
||||
* The method is connected to the Exit button's "Pressed()" signal
|
||||
* in the constructor via ROOT's signal/slot mechanism:
|
||||
* \code
|
||||
* exit->Connect("Pressed()", "PMsgBox", this, "DoExit()");
|
||||
* \endcode
|
||||
*
|
||||
* \note This terminates the entire application, not just the message box window
|
||||
* \note Exit code 0 indicates successful termination
|
||||
*
|
||||
* \see gApplication for ROOT's global application object
|
||||
*/
|
||||
void PMsgBox::DoExit()
|
||||
{
|
||||
gApplication->Terminate(0);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2025 by Bastian M. Wojek / Andreas Suter *
|
||||
* Copyright (C) 2009-2026 by Bastian M. Wojek / Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -49,11 +49,26 @@ using namespace boost::algorithm;
|
||||
|
||||
#include "PMsr2Data.h"
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Constructor
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Constructor
|
||||
* \brief Constructor that initializes the msr2data handler.
|
||||
*
|
||||
* \param ext extension/suffix of the msr-files to be processed
|
||||
* Initializes all member variables and prepares the object for processing.
|
||||
* Sets default values:
|
||||
* - Run number digits: 4 (typical for standard run numbering)
|
||||
* - Global/specific parameter counts: 0
|
||||
* - Header written flag: false
|
||||
* - Run list file flag: false
|
||||
*
|
||||
* All handler pointers (SAX parser, startup handler, data handler, msr handler)
|
||||
* are initialized to nullptr and will be created as needed during processing.
|
||||
*
|
||||
* \param ext File extension for data files (e.g., ".bin", ".root", ".mdu")
|
||||
* This extension is used to locate corresponding data files for each run
|
||||
*
|
||||
* \note The extension should include the leading dot if required
|
||||
*/
|
||||
PMsr2Data::PMsr2Data(const std::string &ext) : fFileExtension(ext), fRunListFile(false), fNumGlobalParam(0), fNumSpecParam(0), fNumTempRunBlocks(0), fRunNumberDigits(4), fHeaderWritten(false)
|
||||
{
|
||||
@@ -65,9 +80,15 @@ PMsr2Data::PMsr2Data(const std::string &ext) : fFileExtension(ext), fRunListFile
|
||||
fMsrHandler = nullptr;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Destructor
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Destructor
|
||||
* \brief Destructor that cleans up resources.
|
||||
*
|
||||
* Clears all vectors and resets iterators. The unique_ptr members
|
||||
* (fRunListFileStream, fSaxParser, fStartupHandler, fDataHandler, fMsrHandler)
|
||||
* are automatically cleaned up through their destructors.
|
||||
*/
|
||||
PMsr2Data::~PMsr2Data()
|
||||
{
|
||||
@@ -76,21 +97,36 @@ PMsr2Data::~PMsr2Data()
|
||||
fIndVar.clear();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// DetermineRunNumberDigits
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Determines the number of digits used for the run number in the data file name from the first msr-file that is processed
|
||||
* If the specified run number is the first one of the list of runs and it cannot be opened, then the rest of the given runs is checked
|
||||
* until an existing msr-file is found
|
||||
* \brief Determines the number of digits used for run number formatting.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - 0 if the number has been determined and set successfully
|
||||
* - -1 in case the msr-file cannot be read
|
||||
* - -2 if the msr-file-number does not match the data-file-number
|
||||
* - -3 if the msr-file does not contain a RUN block
|
||||
* Analyzes the first processable msr-file to determine how many digits are
|
||||
* used for run number formatting in data file names. This ensures consistent
|
||||
* zero-padding when generating new msr-files from templates.
|
||||
*
|
||||
* \param runNo run number of an msr-file
|
||||
* \param normalMode false for global mode
|
||||
* The algorithm:
|
||||
* 1. Attempts to open the msr-file for the specified run number
|
||||
* 2. If in global mode and file not found, tries the "+global" variant
|
||||
* 3. If first run fails, iterates through the run list to find an existing file
|
||||
* 4. Searches the RUN block for the run number in the data file path
|
||||
* 5. Counts leading zeros to determine the digit width
|
||||
*
|
||||
* Example: If the data file is "run_0042.bin", this determines 4 digits.
|
||||
*
|
||||
* \param runNo Run number to analyze
|
||||
* \param normalMode true for normal mode, false for global fitting mode
|
||||
*
|
||||
* \return
|
||||
* - 0 if the number of digits was successfully determined
|
||||
* - -1 if no msr-file could be opened
|
||||
* - -2 if msr-file run number doesn't match data file run number
|
||||
* - -3 if the msr-file contains no RUN block
|
||||
*
|
||||
* \note The determined digit count is stored in fRunNumberDigits
|
||||
* \note In global mode, also checks for files with "+global" suffix
|
||||
*/
|
||||
int PMsr2Data::DetermineRunNumberDigits(unsigned int runNo, bool normalMode) const
|
||||
{
|
||||
@@ -177,13 +213,27 @@ int PMsr2Data::DetermineRunNumberDigits(unsigned int runNo, bool normalMode) con
|
||||
return -3;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// CheckRunNumbersInRange
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Checks if all given run numbers are in the range covered by the number of digits used in the data file name
|
||||
* \brief Validates that all run numbers fit within the determined digit width.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - 0 if everything is fine
|
||||
* - -1 if a given run number is too big
|
||||
* Checks if all run numbers in the run vector can be represented with the
|
||||
* number of digits determined from the data file naming convention. This
|
||||
* prevents formatting errors when generating file names.
|
||||
*
|
||||
* The check has been loosened since 2023 to accommodate LEM run numbers
|
||||
* exceeding 9999 by allowing one extra digit beyond the determined width.
|
||||
*
|
||||
* Maximum allowed run number = 10^(fRunNumberDigits+1) - 1
|
||||
*
|
||||
* \return
|
||||
* - 0 if all run numbers are within the acceptable range
|
||||
* - -1 if any run number exceeds the maximum
|
||||
*
|
||||
* \note Since 2023, uses fRunNumberDigits+1 instead of fRunNumberDigits
|
||||
* to handle larger run numbers at facilities like LEM
|
||||
*/
|
||||
int PMsr2Data::CheckRunNumbersInRange() const
|
||||
{
|
||||
@@ -201,13 +251,18 @@ int PMsr2Data::CheckRunNumbersInRange() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// GetPresentRun
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Determines the current run number
|
||||
* \brief Returns the current run number being processed.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - current run number
|
||||
* - 0 if all runs have been processed already
|
||||
* Retrieves the run number pointed to by the internal iterator.
|
||||
* Used to track progress through the run list during processing.
|
||||
*
|
||||
* \return
|
||||
* - Current run number if processing is ongoing
|
||||
* - 0 if all runs have been processed (iterator at end)
|
||||
*/
|
||||
unsigned int PMsr2Data::GetPresentRun() const
|
||||
{
|
||||
@@ -217,15 +272,20 @@ unsigned int PMsr2Data::GetPresentRun() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// SetRunNumbers (single run)
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Initialization of the internal list of runs using a single run number
|
||||
* \brief Sets a single run number for processing.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* Clears any existing run list and initializes with a single run number.
|
||||
* The internal iterator is reset to point to the beginning.
|
||||
*
|
||||
* \param runNo Run number to process (must be >= 1)
|
||||
*
|
||||
* \return
|
||||
* - 0 if the run number is valid
|
||||
* - 1 otherwise
|
||||
*
|
||||
* \param runNo run number
|
||||
* - 1 if the run number is invalid (< 1)
|
||||
*/
|
||||
int PMsr2Data::SetRunNumbers(unsigned int runNo)
|
||||
{
|
||||
@@ -239,16 +299,24 @@ int PMsr2Data::SetRunNumbers(unsigned int runNo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// SetRunNumbers (range)
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Initialization of the internal list of runs using first and last run numbers
|
||||
* \brief Sets a range of run numbers for processing.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - 0 if the run numbers are valid
|
||||
* - 1 otherwise
|
||||
* Clears any existing run list and populates it with all run numbers
|
||||
* from runNoStart to runNoEnd (inclusive). Handles both ascending
|
||||
* and descending ranges automatically.
|
||||
*
|
||||
* \param runNoStart first run number
|
||||
* \param runNoEnd last run number
|
||||
* \param runNoStart First run number in the range (must be >= 1)
|
||||
* \param runNoEnd Last run number in the range (must be >= 1)
|
||||
*
|
||||
* \return
|
||||
* - 0 if both run numbers are valid
|
||||
* - 1 if either run number is invalid (< 1)
|
||||
*
|
||||
* \note If runNoStart > runNoEnd, the range is generated in descending order
|
||||
*/
|
||||
int PMsr2Data::SetRunNumbers(unsigned int runNoStart, unsigned int runNoEnd)
|
||||
{
|
||||
@@ -268,16 +336,21 @@ int PMsr2Data::SetRunNumbers(unsigned int runNoStart, unsigned int runNoEnd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// SetRunNumbers (explicit vector)
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Initialization of the internal list of runs using explicitly specified run numbers
|
||||
* \brief Sets run numbers from an explicit vector.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* Clears any existing run list and copies the provided vector of run numbers.
|
||||
* All run numbers in the vector must be valid (>= 1).
|
||||
*
|
||||
* \param runListVector Vector containing run numbers to process
|
||||
*
|
||||
* \return
|
||||
* - -1 if the vector is empty
|
||||
* - 0 if all run numbers are valid
|
||||
* - 1 otherwise
|
||||
*
|
||||
* \param runListVector vector containing the run numbers to be processed
|
||||
* - 1 if any run number is invalid (< 1)
|
||||
*/
|
||||
int PMsr2Data::SetRunNumbers(const std::vector<unsigned int> &runListVector)
|
||||
{
|
||||
@@ -295,16 +368,34 @@ int PMsr2Data::SetRunNumbers(const std::vector<unsigned int> &runListVector)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// SetRunNumbers (from file)
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Initialization of the internal list of runs using a run list file
|
||||
* \brief Sets run numbers from a run list file.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* Reads run numbers from a text file with the following format:
|
||||
* - First line: "RUN" followed by optional independent variable names
|
||||
* - Subsequent lines: run number followed by corresponding variable values
|
||||
* - Comments start with '#' and are ignored
|
||||
* - Empty lines are skipped
|
||||
*
|
||||
* Example run list file:
|
||||
* \verbatim
|
||||
* RUN FIELD TEMP
|
||||
* 1234 0.5 295.0
|
||||
* 1235 1.0 295.0 # This is a comment
|
||||
* 1236 1.5 295.0
|
||||
* \endverbatim
|
||||
*
|
||||
* \param runListFile Path to run list file
|
||||
*
|
||||
* \return
|
||||
* - -1 if the run list file cannot be opened
|
||||
* - 0 if all run numbers are valid
|
||||
* - 1 otherwise
|
||||
* - 1 if any run number is invalid (< 1) or file format is incorrect
|
||||
*
|
||||
* \param runListFile name of run list file
|
||||
* \note Sets fRunListFile flag to true and opens stream for reading variables
|
||||
*/
|
||||
int PMsr2Data::SetRunNumbers(const std::string &runListFile)
|
||||
{
|
||||
@@ -366,13 +457,27 @@ int PMsr2Data::SetRunNumbers(const std::string &runListFile)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// ParseXmlStartupFile
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Parse the musrfit startup xml file
|
||||
* \brief Parses the musrfit XML startup file for configuration.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - 0 if everything went fine
|
||||
* - return value of the parseXmlFile function otherwise
|
||||
* Creates a SAX parser and startup handler to read the musrfit_startup.xml
|
||||
* configuration file. This file contains paths, templates, and other settings
|
||||
* needed for msr2data operation.
|
||||
*
|
||||
* The parseXmlFile function is used instead of ParseFile to avoid
|
||||
* environment-specific issues encountered with direct parsing.
|
||||
*
|
||||
* \return
|
||||
* - 0 if parsing succeeded
|
||||
* - Non-zero error code from parseXmlFile if parsing failed
|
||||
*
|
||||
* \note Outputs a warning to stderr if parsing fails
|
||||
*
|
||||
* \see PStartupHandler for XML configuration details
|
||||
* \see parseXmlFile for the parsing implementation
|
||||
*/
|
||||
int PMsr2Data::ParseXmlStartupFile()
|
||||
{
|
||||
@@ -392,15 +497,22 @@ int PMsr2Data::ParseXmlStartupFile()
|
||||
return status;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// ReadMsrFile
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Read in a msr-file into the default structure
|
||||
* \brief Reads and parses an msr-file.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - PMUSR_SUCCESS if everything is OK
|
||||
* - return value of the ReadMsrFile-method otherwise
|
||||
* Creates a new PMsrHandler and uses it to read and parse the specified
|
||||
* msr-file into the internal data structure.
|
||||
*
|
||||
* \param infile name of the msr-file to be read
|
||||
* \param infile Path to the msr-file to read
|
||||
*
|
||||
* \return
|
||||
* - PMUSR_SUCCESS if reading and parsing succeeded
|
||||
* - Error code from PMsrHandler::ReadMsrFile otherwise
|
||||
*
|
||||
* \see PMsrHandler::ReadMsrFile for parsing details
|
||||
*/
|
||||
int PMsr2Data::ReadMsrFile(const std::string &infile) const
|
||||
{
|
||||
@@ -423,14 +535,23 @@ int PMsr2Data::ReadMsrFile(const std::string &infile) const
|
||||
return status;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// GetSingleRunMsrFile
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Read in the single run msr-file corresponding to the position in the run-vector
|
||||
* into a secondary msr-handler different from the class member
|
||||
* \brief Retrieves msr-file handler for a single-run fit file.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - pointer to the secondary msr-handler or 0 in case of an error
|
||||
* Reads the "-OneRunFit" variant of the msr-file for the current run.
|
||||
* This is used when extracting individual run results from global fits.
|
||||
*
|
||||
* The file name format: "<runNumber>-OneRunFit<extension>.msr"
|
||||
*
|
||||
* \return
|
||||
* - Pointer to newly created PMsrHandler on success
|
||||
* - nullptr if file cannot be read or parsed
|
||||
*
|
||||
* \note Caller is responsible for deleting the returned handler
|
||||
* \note Different from the class member fMsrHandler
|
||||
*/
|
||||
PMsrHandler* PMsr2Data::GetSingleRunMsrFile() const
|
||||
{
|
||||
@@ -457,13 +578,23 @@ PMsrHandler* PMsr2Data::GetSingleRunMsrFile() const
|
||||
return singleRunMsrFile;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// ReadRunDataFile
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p> Read in a run data-file
|
||||
* \brief Reads the run data file for the current run.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - 0 if everything is OK
|
||||
* - 1 otherwise
|
||||
* Creates a PRunDataHandler and reads the experimental data file
|
||||
* associated with the current msr-file. Uses data paths from the
|
||||
* startup handler if available, otherwise uses defaults.
|
||||
*
|
||||
* \return
|
||||
* - 0 if all data was successfully read
|
||||
* - 1 if some data files could not be read (with warning)
|
||||
*
|
||||
* \note Outputs a warning to stderr if data is unavailable but continues processing
|
||||
*
|
||||
* \see PRunDataHandler for data file reading details
|
||||
*/
|
||||
int PMsr2Data::ReadRunDataFile()
|
||||
{
|
||||
@@ -2457,13 +2588,23 @@ int PMsr2Data::WriteOutput(const std::string &outfile, const std::vector<unsigne
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// WriteValue (single value)
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p>Write formatted output to column-formatted ASCII output file
|
||||
* \brief Writes a formatted numeric value to output stream.
|
||||
*
|
||||
* \param outFile output file stream to the ASCII file
|
||||
* \param value number to be written to the ASCII file
|
||||
* \param width column width of the ASCII file
|
||||
* Formats the value for column-aligned ASCII output with automatic
|
||||
* selection of scientific notation for very large or very small numbers.
|
||||
*
|
||||
* Formatting rules:
|
||||
* - Scientific notation if |value| >= 1e6 or (|value| < 1e-4 and value != 0)
|
||||
* - Fixed-point notation otherwise
|
||||
* - Left-aligned in field of specified width
|
||||
*
|
||||
* \param outFile Output file stream
|
||||
* \param value Numeric value to write
|
||||
* \param width Column width for formatting
|
||||
*/
|
||||
void PMsr2Data::WriteValue(std::fstream &outFile, const double &value, const unsigned int &width) const
|
||||
{
|
||||
@@ -2474,16 +2615,32 @@ void PMsr2Data::WriteValue(std::fstream &outFile, const double &value, const uns
|
||||
outFile << std::setw(width) << std::left << value;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// WriteValue (value with error)
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p>Write a value to the outFile stream. The string length is determined on its error.
|
||||
* E.g. 17.0023 +- 0.0018, or 73212.081 +- 0.033, etc.
|
||||
* \brief Writes a value with error-based precision formatting.
|
||||
*
|
||||
* \param outFile output stream object
|
||||
* \param value to be written to stream outFile
|
||||
* \param errValue error of the value. needed to determine the needed accuracy
|
||||
* \param width field width for outFile for formatted output
|
||||
* \param db true for db-file output, false for dat-file output. Needed to have at least on space between numbers for dat-file output
|
||||
* Formats output with precision determined by the error value, ensuring
|
||||
* significant digits are preserved appropriately. The precision is calculated
|
||||
* based on the first significant digit of the error.
|
||||
*
|
||||
* Examples:
|
||||
* - value=17.0023 ± errValue=0.0018 → formatted with 4 decimal places
|
||||
* - value=73212.081 ± errValue=0.033 → formatted with 2 decimal places
|
||||
*
|
||||
* Formatting rules:
|
||||
* - Precision based on error's first significant digit
|
||||
* - Scientific notation if |value| >= 1e6 or (|value| < 1e-4 and value != 0)
|
||||
* - Extra space added after value in ASCII mode for readability
|
||||
*
|
||||
* \param outFile Output file stream
|
||||
* \param value Numeric value to write
|
||||
* \param errValue Error/uncertainty value (determines precision)
|
||||
* \param width Field width for formatted output
|
||||
* \param db true for DB format, false for ASCII format (adds extra space)
|
||||
*
|
||||
* \see GetFirstSignificantDigit for precision calculation
|
||||
*/
|
||||
void PMsr2Data::WriteValue(std::fstream &outFile, const double &value, const double &errValue, const unsigned int &width, const bool &db) const
|
||||
{
|
||||
@@ -2509,14 +2666,28 @@ void PMsr2Data::WriteValue(std::fstream &outFile, const double &value, const dou
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// GetFirstSignificantDigit
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p>Determines the first significant digit of the provided number value.
|
||||
* E.g. for value=2.03 it will return 1, for value=0.00023 it will return 4, etc.
|
||||
* \brief Determines the position of the first significant digit.
|
||||
*
|
||||
* \param value for which the first significant digit needs to be determined.
|
||||
* Calculates how many decimal places are needed to reach the first
|
||||
* significant digit by repeatedly multiplying by 10 until the value
|
||||
* is >= 1.0. This is used for precision control in output formatting.
|
||||
*
|
||||
* \return first significant digit of the provided number value
|
||||
* Examples:
|
||||
* - value = 2.03 → returns 1 (first significant digit in tenths place)
|
||||
* - value = 0.00023 → returns 4 (first significant digit in ten-thousandths)
|
||||
* - value = 0.5 → returns 1
|
||||
*
|
||||
* \param value Value to analyze (typically an error/uncertainty)
|
||||
*
|
||||
* \return
|
||||
* - Position of first significant digit (1-19)
|
||||
* - 6 if no significant digit found after 20 iterations (default precision)
|
||||
*
|
||||
* \note Maximum 20 iterations to prevent infinite loops
|
||||
*/
|
||||
int PMsr2Data::GetFirstSignificantDigit(const double &value) const
|
||||
{
|
||||
@@ -2538,15 +2709,26 @@ int PMsr2Data::GetFirstSignificantDigit(const double &value) const
|
||||
return prec+1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// InParameterList
|
||||
//-------------------------------------------------------------
|
||||
/**
|
||||
* <p>Checks paramValue is found in the paramList. If paramList
|
||||
* is empty, ALL paramValues will be accepted, i.e. return true.
|
||||
* \brief Checks if a parameter index should be included in output.
|
||||
*
|
||||
* \param paramValue paramValue to be checked
|
||||
* \param paramList parameter list
|
||||
* Determines whether a given parameter should be written to the output
|
||||
* file based on the user-specified parameter list. If the parameter list
|
||||
* is empty, all parameters are included by default.
|
||||
*
|
||||
* \return true if the paramValue if found in paramList, or true if paramList is empty.
|
||||
* \param paramValue Zero-based parameter index to check
|
||||
* \param paramList Vector of one-based parameter numbers to output
|
||||
* (empty vector means output all parameters)
|
||||
*
|
||||
* \return
|
||||
* - true if paramValue should be included in output
|
||||
* - true if paramList is empty (output all parameters)
|
||||
* - false if paramValue is not in the list
|
||||
*
|
||||
* \note paramValue is zero-based while paramList contains one-based indices
|
||||
*/
|
||||
bool PMsr2Data::InParameterList(const unsigned int ¶mValue, const std::vector<unsigned int> ¶mList) const
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -45,13 +45,28 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Constructor that initializes the MSR handler.
|
||||
*
|
||||
* \param fileName name of a msr-file.
|
||||
* Initializes all internal data structures and extracts the directory path
|
||||
* from the MSR file name. The directory path is used for resolving relative
|
||||
* paths in the MSR file (e.g., for data files).
|
||||
*
|
||||
* Initialization includes:
|
||||
* - Setting default values for all MSR blocks
|
||||
* - Initializing statistics structure (invalid, χ² mode, min=-1, ndf=0)
|
||||
* - Extracting file directory path from file name
|
||||
* - Setting block counter to 0
|
||||
*
|
||||
* \param fileName Path to MSR file (absolute or relative)
|
||||
* \param startupOptions Optional pointer to startup configuration from musrfit_startup.xml
|
||||
* \param fourierOnly If true, only parse Fourier-related blocks (used by musrFT tool)
|
||||
*
|
||||
* \note If fileName contains "/" characters, the directory path is extracted
|
||||
* and stored in fMsrFileDirectoryPath; otherwise defaults to "./"
|
||||
*/
|
||||
PMsrHandler::PMsrHandler(const Char_t *fileName, PStartupOptions *startupOptions, const Bool_t fourierOnly) :
|
||||
fFourierOnly(fourierOnly), fStartupOptions(startupOptions), fFileName(fileName)
|
||||
{
|
||||
{
|
||||
// init variables
|
||||
fMsrBlockCounter = 0;
|
||||
|
||||
@@ -83,7 +98,19 @@ PMsrHandler::PMsrHandler(const Char_t *fileName, PStartupOptions *startupOptions
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor
|
||||
* \brief Destructor that cleans up all data structures.
|
||||
*
|
||||
* Clears all vectors and releases memory:
|
||||
* - Parameter list
|
||||
* - Theory lines
|
||||
* - Functions lines
|
||||
* - Run configurations
|
||||
* - MINUIT commands
|
||||
* - Plot settings
|
||||
* - Statistics data
|
||||
* - Parameter usage flags
|
||||
*
|
||||
* The unique_ptr member (fFuncHandler) is automatically cleaned up.
|
||||
*/
|
||||
PMsrHandler::~PMsrHandler()
|
||||
{
|
||||
@@ -103,11 +130,46 @@ PMsrHandler::~PMsrHandler()
|
||||
// ReadMsrFile (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Reads and parses a msr-file.
|
||||
* \brief Reads and parses the MSR file.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - PMUSR_SUCCESS if everything is OK
|
||||
* - line number if an error in the MSR file was encountered which cannot be handled.
|
||||
* Performs comprehensive parsing of all MSR file blocks in the following order:
|
||||
* 1. TITLE - File description
|
||||
* 2. FITPARAMETER - Fit parameters with values, errors, and constraints
|
||||
* 3. THEORY - Asymmetry/relaxation function definitions
|
||||
* 4. FUNCTIONS (optional) - User-defined mathematical functions
|
||||
* 5. GLOBAL (optional) - Global fit settings
|
||||
* 6. RUN - Data file specifications and fit ranges
|
||||
* 7. COMMANDS - MINUIT fitting commands
|
||||
* 8. FOURIER (optional) - Fourier transform parameters
|
||||
* 9. PLOT (optional) - Plotting parameters
|
||||
* 10. STATISTIC - Fit results (χ², NDF, convergence)
|
||||
*
|
||||
* After parsing, performs extensive validation:
|
||||
* - Checks for legacy lifetimecorrection syntax
|
||||
* - Validates RUN block integrity (required fields, grouping consistency)
|
||||
* - Verifies parameter name uniqueness
|
||||
* - Checks map index validity
|
||||
* - Validates user-defined functions
|
||||
* - Verifies histogram grouping consistency
|
||||
* - Checks addrun parameter references
|
||||
* - Validates RRF (Rotating Reference Frame) settings
|
||||
* - Checks real FFT requirements
|
||||
* - Validates maximum likelihood settings
|
||||
*
|
||||
* Error Handling:
|
||||
* - Detailed error messages are written to stderr
|
||||
* - Error messages are accumulated in fLastErrorMsg for programmatic access
|
||||
* - Returns line number where error occurred for syntax errors
|
||||
*
|
||||
* \return
|
||||
* - PMUSR_SUCCESS (0) if parsing succeeded
|
||||
* - PMUSR_MSR_FILE_NOT_FOUND if file cannot be opened
|
||||
* - PMUSR_MSR_SYNTAX_ERROR if syntax error encountered
|
||||
* - Positive line number if parsing error occurred at specific line
|
||||
*
|
||||
* \note In Fourier-only mode (fFourierOnly=true), only relevant blocks are parsed
|
||||
*
|
||||
* \see HandleFitParameterEntry, HandleTheoryEntry, HandleRunEntry for block parsing
|
||||
*/
|
||||
Int_t PMsrHandler::ReadMsrFile()
|
||||
{
|
||||
@@ -341,15 +403,42 @@ Int_t PMsrHandler::ReadMsrFile()
|
||||
// WriteMsrLogFile (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Writes a mlog-file.
|
||||
* \brief Writes an MSR log file (.mlog) with parsed MSR content.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - PMUSR_SUCCESS everything is OK
|
||||
* - PMUSR_MSR_LOG_FILE_WRITE_ERROR msr-/mlog-file couldn't be opened
|
||||
* - PMUSR_MSR_SYNTAX_ERROR a syntax error has been encountered
|
||||
* Creates a log file with the same base name as the MSR file but with .mlog
|
||||
* extension. The log file contains the parsed and formatted MSR structure,
|
||||
* which is useful for:
|
||||
* - Debugging MSR file parsing
|
||||
* - Verifying parameter interpretation
|
||||
* - Checking fit range calculations
|
||||
* - Reviewing theory and function definitions
|
||||
*
|
||||
* \param messages if true some additional messages concerning the statistic block are written.
|
||||
* When using musrt0, messages will be set to false.
|
||||
* The log file format mirrors the MSR file structure but with:
|
||||
* - Standardized formatting and precision
|
||||
* - Expanded parameter values
|
||||
* - Calculated fit ranges (in bins and microseconds)
|
||||
* - Resolved function definitions
|
||||
* - Complete statistics (if available)
|
||||
*
|
||||
* Processing includes:
|
||||
* - Re-reading original MSR file to preserve comments and structure
|
||||
* - Identifying missing tags (t0, background, data) in RUN blocks
|
||||
* - Formatting numeric values with appropriate precision
|
||||
* - Writing all MSR blocks in canonical format
|
||||
*
|
||||
* \param messages If true, includes additional informational messages about
|
||||
* the statistics block. Set to false when called from musrt0
|
||||
* to suppress messages.
|
||||
*
|
||||
* \return
|
||||
* - PMUSR_SUCCESS if log file written successfully
|
||||
* - PMUSR_MSR_LOG_FILE_WRITE_ERROR if MSR or log file cannot be opened
|
||||
* - PMUSR_MSR_SYNTAX_ERROR if syntax error encountered during processing
|
||||
*
|
||||
* \note The log file name is constructed by replacing the MSR file extension
|
||||
* with ".mlog" (e.g., "run1234.msr" → "run1234.mlog")
|
||||
*
|
||||
* \see WriteMsrFile for writing updated MSR files
|
||||
*/
|
||||
Int_t PMsrHandler::WriteMsrLogFile(const Bool_t messages)
|
||||
{
|
||||
@@ -725,6 +814,10 @@ Int_t PMsrHandler::WriteMsrLogFile(const Bool_t messages)
|
||||
fout.width(16);
|
||||
fout << std::left << "packing";
|
||||
fout << fGlobal.GetPacking() << std::endl;
|
||||
} else if (sstr.BeginsWith("deadtime-cor")) {
|
||||
fout.width(16);
|
||||
fout << std::left << "deadtime-cor";
|
||||
fout << fGlobal.GetDeadTimeCorrection() << std::endl;
|
||||
} else {
|
||||
fout << str.Data() << std::endl;
|
||||
}
|
||||
@@ -1068,6 +1161,10 @@ Int_t PMsrHandler::WriteMsrLogFile(const Bool_t messages)
|
||||
fout.width(16);
|
||||
fout << std::left << "packing";
|
||||
fout << fRuns[runNo].GetPacking() << std::endl;
|
||||
} else if (sstr.BeginsWith("deadtime-cor")) {
|
||||
fout.width(16);
|
||||
fout << std::left << "deadtime-cor";
|
||||
fout << fRuns[runNo].GetDeadTimeCorrection() << std::endl;
|
||||
} else {
|
||||
fout << str.Data() << std::endl;
|
||||
}
|
||||
@@ -1549,13 +1646,51 @@ Int_t PMsrHandler::WriteMsrLogFile(const Bool_t messages)
|
||||
// WriteMsrFile (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Writes a msr-file from the internal data structures
|
||||
* \brief Writes an MSR file from internal data structures.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - PMUSR_SUCCESS everything is OK
|
||||
* - PMUSR_MSR_FILE_WRITE_ERROR msr output file couldn't be opened
|
||||
* Creates a complete MSR file with all blocks, typically called after fitting
|
||||
* to save updated parameter values, errors, and fit statistics. The file
|
||||
* includes properly formatted blocks in the standard MSR file order.
|
||||
*
|
||||
* \param filename The name of the output file.
|
||||
* **MSR File Structure Written:**
|
||||
* 1. TITLE block
|
||||
* 2. FITPARAMETER block (with fitted values and errors)
|
||||
* 3. THEORY block
|
||||
* 4. FUNCTIONS block (if functions are defined)
|
||||
* 5. GLOBAL block (if global settings exist)
|
||||
* 6. RUN blocks (one per run)
|
||||
* 7. COMMANDS block
|
||||
* 8. FOURIER block (if Fourier parameters are defined)
|
||||
* 9. PLOT blocks (if plot settings exist)
|
||||
* 10. STATISTIC block (with fit results)
|
||||
*
|
||||
* **Comment Preservation:**
|
||||
* The comment maps allow preserving user comments from specific MSR blocks.
|
||||
* Comments are inserted before the corresponding line based on the map key
|
||||
* (line number). This is useful when updating MSR files while maintaining
|
||||
* documentation.
|
||||
*
|
||||
* **Formatting:**
|
||||
* - Parameters: Right-aligned numbers, left-aligned names and values
|
||||
* - Precision: 6 significant digits for floating-point values
|
||||
* - Boundaries: Properly formatted lower/upper limits
|
||||
* - Separators: Dashed lines between major sections
|
||||
*
|
||||
* \param filename Output MSR file path
|
||||
* \param commentsPAR Optional map of line number → comment for FITPARAMETER block
|
||||
* \param commentsTHE Optional map of line number → comment for THEORY block
|
||||
* \param commentsFUN Optional map of line number → comment for FUNCTIONS block
|
||||
* \param commentsRUN Optional map of line number → comment for RUN blocks
|
||||
*
|
||||
* \return
|
||||
* - PMUSR_SUCCESS if file written successfully
|
||||
* - PMUSR_MSR_FILE_WRITE_ERROR if output file cannot be opened
|
||||
*
|
||||
* \note Comments are removed from the maps after being written
|
||||
* \note The STATISTIC block content depends on fCopyStatisticsBlock flag
|
||||
*
|
||||
* \see WriteMsrLogFile for writing debug/verification log files
|
||||
* \see SetMsrStatisticMin, SetMsrStatisticNdf for updating statistics
|
||||
*/
|
||||
Int_t PMsrHandler::WriteMsrFile(const Char_t *filename, std::map<UInt_t, TString> *commentsPAR, \
|
||||
std::map<UInt_t, TString> *commentsTHE, \
|
||||
@@ -3207,6 +3342,20 @@ Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines)
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
} else if (iter->fLine.BeginsWith("deadtime-cor", TString::kIgnoreCase)) { // deadtime correction
|
||||
if (tokens->GetEntries() < 2) {
|
||||
error = true;
|
||||
} else {
|
||||
ostr = dynamic_cast<TObjString*>(tokens->At(1));
|
||||
str = ostr->GetString();
|
||||
if (!str.CompareTo("no", TString::kIgnoreCase) ||
|
||||
!str.CompareTo("file", TString::kIgnoreCase) ||
|
||||
!str.CompareTo("estimate", TString::kIgnoreCase)) {
|
||||
global.SetDeadTimeCorrection(str);
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clean up
|
||||
@@ -3804,6 +3953,27 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines)
|
||||
}
|
||||
}
|
||||
|
||||
// deadtime-correction -----------------------------------
|
||||
if (iter->fLine.BeginsWith("deadtime-cor", TString::kIgnoreCase)) { // deadtime correction
|
||||
|
||||
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
|
||||
|
||||
if (tokens->GetEntries() < 2) {
|
||||
error = true;
|
||||
} else {
|
||||
ostr = dynamic_cast<TObjString*>(tokens->At(1));
|
||||
str = ostr->GetString();
|
||||
if (!str.CompareTo("no", TString::kIgnoreCase) ||
|
||||
!str.CompareTo("file", TString::kIgnoreCase) ||
|
||||
!str.CompareTo("estimate", TString::kIgnoreCase)) {
|
||||
param.SetDeadTimeCorrection(str);
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// xy-data -----------------------------------------------
|
||||
if (line.BeginsWith("xy-data", TString::kIgnoreCase)) {
|
||||
|
||||
@@ -6596,7 +6766,11 @@ Bool_t PMsrHandler::CheckRRFSettings()
|
||||
*/
|
||||
Bool_t PMsrHandler::CheckRealFFT()
|
||||
{
|
||||
// check
|
||||
// if no Fourier block is present, nothing needs to be checked
|
||||
if (!fFourier.fFourierBlockPresent)
|
||||
return true;
|
||||
|
||||
// if Fourier is set to power spectra, no phase checks are needed
|
||||
if (fFourier.fPlotTag == FOURIER_PLOT_POWER)
|
||||
return true;
|
||||
|
||||
@@ -6617,15 +6791,15 @@ Bool_t PMsrHandler::CheckRealFFT()
|
||||
|
||||
// make sure that FOURIER phases are defined
|
||||
if ((fFourier.fPhase.size() == 0) && (fFourier.fPhaseParamNo.size() == 0)) {
|
||||
fLastErrorMsg.str("");
|
||||
fLastErrorMsg.clear();
|
||||
fLastErrorMsg << ">> PMsrHandler::ReadMsrFile: **ERROR** for FOURIER plot != POWER,\n";
|
||||
fLastErrorMsg << ">> phases need to be defined in the FOURIER block!\n";
|
||||
fLastErrorMsg << ">> Examples:\n";
|
||||
fLastErrorMsg << ">> phase parR7 par9 par13 par16\n";
|
||||
fLastErrorMsg << ">> where parR7 is the reference phase, and the others the relative phases.\n";
|
||||
fLastErrorMsg << ">> I.e. phase of run 2: parR7 + par9, etc.\n";
|
||||
fLastErrorMsg << ">> For further details see the docu.\n";
|
||||
fLastErrorMsg.str("");
|
||||
fLastErrorMsg.clear();
|
||||
fLastErrorMsg << ">> PMsrHandler::ReadMsrFile: **ERROR** for FOURIER plot != POWER,\n";
|
||||
fLastErrorMsg << ">> phases need to be defined in the FOURIER block!\n";
|
||||
fLastErrorMsg << ">> Examples:\n";
|
||||
fLastErrorMsg << ">> phase parR7 par9 par13 par16\n";
|
||||
fLastErrorMsg << ">> where parR7 is the reference phase, and the others the relative phases.\n";
|
||||
fLastErrorMsg << ">> I.e. phase of run 2: parR7 + par9, etc.\n";
|
||||
fLastErrorMsg << ">> For further details see the docu.\n";
|
||||
std::cerr << std::endl << fLastErrorMsg.str();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -721,6 +721,22 @@ PRawRunDataSet* PRawRunData::GetDataSet(const UInt_t idx, Bool_t wantHistoNo)
|
||||
return fData.GetSet(idx);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// DeadTimeCorrectionReady (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Checks if deadtime correction information is sufficient to apply it.
|
||||
* This means that fNumberOfGoodFrames must be present and the deadtime
|
||||
* parameter vector.
|
||||
*
|
||||
* @return true if ready to apply deadtime correctio, false otherwise
|
||||
*/
|
||||
const Bool_t PRawRunData::DeadTimeCorrectionReady()
|
||||
{
|
||||
if ((fNumberOfGoodFrames > 0) && (fDeadTimeParam.size() > 0))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// SetRingAnode (public)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -50,7 +50,10 @@ ClassImp(PMusrCanvasPlotRange)
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Constructor initializing plot range to undefined state.
|
||||
*
|
||||
* Sets both X and Y ranges as not present and initializes all range
|
||||
* values to zero. Ranges must be explicitly set via SetXRange/SetYRange.
|
||||
*/
|
||||
PMusrCanvasPlotRange::PMusrCanvasPlotRange()
|
||||
{
|
||||
@@ -67,10 +70,13 @@ PMusrCanvasPlotRange::PMusrCanvasPlotRange()
|
||||
// SetXRange (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Sets the x-range values.
|
||||
* \brief Sets the X-axis range and marks it as present.
|
||||
*
|
||||
* \param xmin minimum range value
|
||||
* \param xmax maximum range value
|
||||
* Automatically swaps values if xmin > xmax to ensure proper ordering.
|
||||
* Outputs a warning to stderr when swapping occurs.
|
||||
*
|
||||
* \param xmin Minimum X value
|
||||
* \param xmax Maximum X value
|
||||
*/
|
||||
void PMusrCanvasPlotRange::SetXRange(Double_t xmin, Double_t xmax)
|
||||
{
|
||||
@@ -89,10 +95,13 @@ void PMusrCanvasPlotRange::SetXRange(Double_t xmin, Double_t xmax)
|
||||
// SetYRange (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Sets the y-range values.
|
||||
* \brief Sets the Y-axis range and marks it as present.
|
||||
*
|
||||
* \param ymin minimum range value
|
||||
* \param ymax maximum range value
|
||||
* Automatically swaps values if ymin > ymax to ensure proper ordering.
|
||||
* Outputs a warning to stderr when swapping occurs.
|
||||
*
|
||||
* \param ymin Minimum Y value
|
||||
* \param ymax Maximum Y value
|
||||
*/
|
||||
void PMusrCanvasPlotRange::SetYRange(Double_t ymin, Double_t ymax)
|
||||
{
|
||||
@@ -114,7 +123,19 @@ ClassImpQ(PMusrCanvas)
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Default constructor initializing canvas to undefined state.
|
||||
*
|
||||
* Initializes all member variables to default values:
|
||||
* - No timeout
|
||||
* - N0 and background scaling enabled
|
||||
* - Not valid (requires proper initialization via other constructors)
|
||||
* - Data view mode
|
||||
* - All pointers set to nullptr
|
||||
* - Fourier and average structures initialized
|
||||
* - No explicit ranges set
|
||||
*
|
||||
* This constructor creates an invalid canvas that cannot be used directly.
|
||||
* Use one of the full constructors to create a functional canvas.
|
||||
*/
|
||||
PMusrCanvas::PMusrCanvas()
|
||||
{
|
||||
@@ -156,18 +177,30 @@ PMusrCanvas::PMusrCanvas()
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor.
|
||||
* \brief Basic constructor creating canvas with default Fourier settings.
|
||||
*
|
||||
* \param number The plot number of the msr-file PLOT block
|
||||
* \param title Title to be displayed
|
||||
* \param wtopx top x coordinate (in pixels) to place the canvas.
|
||||
* \param wtopy top y coordinate (in pixels) to place the canvas.
|
||||
* \param ww width (in pixels) of the canvas.
|
||||
* \param wh height (in pixels) of the canvas.
|
||||
* \param batch flag: if set true, the canvas will not be displayed. This is used when just dumping of a
|
||||
* graphical output file is wished.
|
||||
* \param fourier flag: if set true, the canvas will present the Fourier view.
|
||||
* \param avg flag: if set true, the canvas will present the averages data/Fourier view.
|
||||
* Creates a functional PMusrCanvas with standard Fourier transform settings
|
||||
* and default markers/colors. This is the simpler constructor for cases where
|
||||
* custom Fourier parameters or plot styling are not needed.
|
||||
*
|
||||
* Initialization sequence:
|
||||
* 1. Initializes member variables
|
||||
* 2. Sets up default Fourier parameters (via InitFourier)
|
||||
* 3. Initializes average data structures (via InitAverage)
|
||||
* 4. Creates ROOT graphics style (via CreateStyle)
|
||||
* 5. Creates canvas pads and menus (via InitMusrCanvas)
|
||||
* 6. Sets histogram minimum to zero for proper bar chart display
|
||||
*
|
||||
* \param number Plot number from MSR file PLOT block
|
||||
* \param title Canvas title to display
|
||||
* \param wtopx Top-left X coordinate of canvas window (pixels)
|
||||
* \param wtopy Top-left Y coordinate of canvas window (pixels)
|
||||
* \param ww Canvas width (pixels)
|
||||
* \param wh Canvas height (pixels)
|
||||
* \param batch If true, run in batch mode without GUI display (for file export)
|
||||
* \param fourier If true, start with Fourier view instead of time domain
|
||||
* \param avg If true, start with averaged data view
|
||||
* \param theoAsData If true, calculate theory only at data points (faster)
|
||||
*/
|
||||
PMusrCanvas::PMusrCanvas(const Int_t number, const Char_t* title,
|
||||
Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh,
|
||||
@@ -203,21 +236,37 @@ PMusrCanvas::PMusrCanvas(const Int_t number, const Char_t* title,
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor.
|
||||
* \brief Full constructor with custom Fourier settings and plot styling.
|
||||
*
|
||||
* \param number The plot number of the msr-file PLOT block
|
||||
* \param title Title to be displayed
|
||||
* \param wtopx top x coordinate (in pixels) to place the canvas.
|
||||
* \param wtopy top y coordinate (in pixels) to place the canvas.
|
||||
* \param ww width (in pixels) of the canvas.
|
||||
* \param wh height (in pixels) of the canvas.
|
||||
* \param fourierDefault structure holding the pre-defined settings for a Fourier transform
|
||||
* \param markerList pre-defined list of markers
|
||||
* \param colorList pre-defined list of colors
|
||||
* \param batch flag: if set true, the canvas will not be displayed. This is used when just dumping of a
|
||||
* graphical output file is wished.
|
||||
* \param fourier flag: if set true, the canvas will present the Fourier view.
|
||||
* \param avg flag: if set true, the canvas will present the averages data/Fourier view.
|
||||
* Creates a PMusrCanvas with user-specified Fourier transform parameters,
|
||||
* custom marker styles, and color schemes. This constructor provides maximum
|
||||
* control over canvas appearance and behavior.
|
||||
*
|
||||
* The marker and color lists allow customization of how multiple datasets
|
||||
* appear in plots. Each dataset uses the marker/color at the corresponding
|
||||
* index in the provided vectors.
|
||||
*
|
||||
* Initialization sequence:
|
||||
* 1. Initializes member variables with custom settings
|
||||
* 2. Copies Fourier parameters, marker list, and color list
|
||||
* 3. Initializes average data structures
|
||||
* 4. Creates ROOT graphics style
|
||||
* 5. Creates canvas pads and menus
|
||||
* 6. Sets histogram minimum to zero for proper bar chart display
|
||||
*
|
||||
* \param number Plot number from MSR file PLOT block
|
||||
* \param title Canvas title to display
|
||||
* \param wtopx Top-left X coordinate of canvas window (pixels)
|
||||
* \param wtopy Top-left Y coordinate of canvas window (pixels)
|
||||
* \param ww Canvas width (pixels)
|
||||
* \param wh Canvas height (pixels)
|
||||
* \param fourierDefault Fourier transform parameters (ranges, apodization, etc.)
|
||||
* \param markerList Vector of ROOT marker style indices (e.g., 20=circle, 21=square)
|
||||
* \param colorList Vector of ROOT color indices (e.g., 1=black, 2=red, 4=blue)
|
||||
* \param batch If true, run in batch mode without GUI display
|
||||
* \param fourier If true, start with Fourier view
|
||||
* \param avg If true, start with averaged data view
|
||||
* \param theoAsData If true, calculate theory only at data points
|
||||
*/
|
||||
PMusrCanvas::PMusrCanvas(const Int_t number, const Char_t* title,
|
||||
Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -44,7 +44,9 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor.
|
||||
* \brief Default constructor that initializes all member variables.
|
||||
*
|
||||
* Calls InitData() to set default values for all member variables.
|
||||
*/
|
||||
PMusrT0Data::PMusrT0Data()
|
||||
{
|
||||
@@ -55,7 +57,10 @@ PMusrT0Data::PMusrT0Data()
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor.
|
||||
* \brief Destructor that cleans up all vector containers.
|
||||
*
|
||||
* Clears all vectors including raw run data references, histogram numbers,
|
||||
* t0 values, and addrun t0 values.
|
||||
*/
|
||||
PMusrT0Data::~PMusrT0Data()
|
||||
{
|
||||
@@ -71,7 +76,10 @@ PMusrT0Data::~PMusrT0Data()
|
||||
// InitData
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Initialize the necessary variables.
|
||||
* \brief Initializes all member variables to default values.
|
||||
*
|
||||
* Sets all indices to -1, flags to default states, and clears all vectors.
|
||||
* This method is called by the constructor and can be used to reset the object.
|
||||
*/
|
||||
void PMusrT0Data::InitData()
|
||||
{
|
||||
@@ -94,13 +102,10 @@ void PMusrT0Data::InitData()
|
||||
// GetRawRunData
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Returns the raw run data set with index idx.
|
||||
* \brief Returns pointer to raw run data at the specified index.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - raw run data set
|
||||
* - 0 pointer, if idx is out of range
|
||||
*
|
||||
* \param idx index of the raw run data
|
||||
* \param idx Index of raw run data (0=main run, >0=addruns)
|
||||
* \return Pointer to PRawRunData object, or nullptr if idx is out of range
|
||||
*/
|
||||
PRawRunData* PMusrT0Data::GetRawRunData(Int_t idx)
|
||||
{
|
||||
@@ -114,13 +119,10 @@ PRawRunData* PMusrT0Data::GetRawRunData(Int_t idx)
|
||||
// GetHistoNo
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get histogram number of a run.
|
||||
* \brief Returns histogram number at the specified index.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - histogram number
|
||||
* - -1 if index is out of range
|
||||
*
|
||||
* \param idx index of the run (msr-file).
|
||||
* \param idx Index into histogram number vector
|
||||
* \return Histogram number (with Red/Green offset applied), or -1 if out of range
|
||||
*/
|
||||
Int_t PMusrT0Data::GetHistoNo(UInt_t idx)
|
||||
{
|
||||
@@ -134,13 +136,10 @@ Int_t PMusrT0Data::GetHistoNo(UInt_t idx)
|
||||
// GetT0Bin
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get t0 (in bin) of a run.
|
||||
* \brief Returns t0 bin value for the main run at the specified index.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - t0 bin
|
||||
* - -1 if index is out of range
|
||||
*
|
||||
* \param idx index of the run (msr-file).
|
||||
* \param idx Index into main run t0 vector
|
||||
* \return t0 bin value, or -1 if out of range
|
||||
*/
|
||||
Int_t PMusrT0Data::GetT0Bin(UInt_t idx)
|
||||
{
|
||||
@@ -154,13 +153,10 @@ Int_t PMusrT0Data::GetT0Bin(UInt_t idx)
|
||||
// GetAddT0BinSize
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get addt0 size of a run, i.e. the number of addt0's for a given msr-file run.
|
||||
* \brief Returns number of t0 bins for the specified addrun.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - number of addt0's
|
||||
* - -1 if index is out of range
|
||||
*
|
||||
* \param idx index of the run (msr-file).
|
||||
* \param idx Addrun index
|
||||
* \return Number of t0 bin values for this addrun, or 0 if out of range
|
||||
*/
|
||||
UInt_t PMusrT0Data::GetAddT0BinSize(UInt_t idx)
|
||||
{
|
||||
@@ -174,14 +170,11 @@ UInt_t PMusrT0Data::GetAddT0BinSize(UInt_t idx)
|
||||
// GetAddT0Bin
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get addt0 (in bin) of a run.
|
||||
* \brief Returns t0 bin value for a specific addrun and histogram index.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - addt0 bin
|
||||
* - -1 if index is out of range
|
||||
*
|
||||
* \param addRunIdx index of the addrun
|
||||
* \param idx index of the run (msr-file).
|
||||
* \param addRunIdx Addrun index
|
||||
* \param idx Histogram index within the addrun
|
||||
* \return t0 bin value, or -1 if either index is out of range
|
||||
*/
|
||||
Int_t PMusrT0Data::GetAddT0Bin(UInt_t addRunIdx, UInt_t idx)
|
||||
{
|
||||
@@ -198,10 +191,12 @@ Int_t PMusrT0Data::GetAddT0Bin(UInt_t addRunIdx, UInt_t idx)
|
||||
// SetT0Bin
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Set t0 value.
|
||||
* \brief Sets t0 bin value for the main run at the specified index.
|
||||
*
|
||||
* \param val t0 value to be set
|
||||
* \param idx index at which t0 shall be set.
|
||||
* Automatically resizes the t0 vector if idx is beyond current size.
|
||||
*
|
||||
* \param val t0 bin value to set
|
||||
* \param idx Index at which to set the t0 value
|
||||
*/
|
||||
void PMusrT0Data::SetT0Bin(UInt_t val, UInt_t idx)
|
||||
{
|
||||
@@ -215,11 +210,13 @@ void PMusrT0Data::SetT0Bin(UInt_t val, UInt_t idx)
|
||||
// SetAddT0Bin
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Set addt0 value.
|
||||
* \brief Sets t0 bin value for a specific addrun and histogram index.
|
||||
*
|
||||
* \param val t0 value to be set
|
||||
* \param addRunIdx addt0 index (for each addrun, there has to be an addt0)
|
||||
* \param idx index at which t0 shall be set.
|
||||
* Automatically resizes vectors if indices are beyond current size.
|
||||
*
|
||||
* \param val t0 bin value to set
|
||||
* \param addRunIdx Addrun index (each addrun needs its own t0 values)
|
||||
* \param idx Histogram index within the addrun
|
||||
*/
|
||||
void PMusrT0Data::SetAddT0Bin(UInt_t val, UInt_t addRunIdx, UInt_t idx)
|
||||
{
|
||||
@@ -240,7 +237,10 @@ ClassImpQ(PMusrT0)
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor.
|
||||
* \brief Default constructor that creates an invalid PMusrT0 instance.
|
||||
*
|
||||
* Initializes all member variables to default values. The instance is marked
|
||||
* as invalid (fValid=false) since no raw data has been provided.
|
||||
*/
|
||||
PMusrT0::PMusrT0()
|
||||
{
|
||||
@@ -264,9 +264,15 @@ PMusrT0::PMusrT0()
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Main constructor that initializes the GUI with raw run data.
|
||||
*
|
||||
* \param data raw run data set
|
||||
* Creates and initializes the interactive t0/range determination GUI. The constructor:
|
||||
* - Validates raw data availability and histogram presence
|
||||
* - Creates histogram from raw data (single or grouped/added)
|
||||
* - Estimates initial t0 by finding the maximum bin value
|
||||
* - Sets up canvas title with run name, histogram number, and detector tag
|
||||
*
|
||||
* \param data PMusrT0Data object containing raw run data and configuration
|
||||
*/
|
||||
PMusrT0::PMusrT0(PMusrT0Data &data) : fMusrT0Data(data)
|
||||
{
|
||||
@@ -535,7 +541,12 @@ PMusrT0::PMusrT0(PMusrT0Data &data) : fMusrT0Data(data)
|
||||
// Done (SIGNAL)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Signal emitted if the user wants to terminate the application.
|
||||
* \brief Emits Done signal to terminate the interactive session.
|
||||
*
|
||||
* This ROOT signal is emitted when the user finishes t0/range determination
|
||||
* or closes the canvas. The status value determines the scope of termination.
|
||||
*
|
||||
* \param status Exit status: 0=local quit, 1=quit application, 2=global quit
|
||||
*/
|
||||
void PMusrT0::Done(Int_t status)
|
||||
{
|
||||
@@ -546,25 +557,29 @@ void PMusrT0::Done(Int_t status)
|
||||
// HandleCmdKey (SLOT)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Filters keyboard and mouse events, and if they are a command key (see below) carries out the
|
||||
* necessary actions.
|
||||
* <p>Currently implemented command keys:
|
||||
* - 'q' close the currently shown canvas
|
||||
* - 'Q' quite the application
|
||||
* - 'u' unzoom to the original range
|
||||
* - 'z' zoom to the region aroung t0
|
||||
* - 's' show/hide (toggle) the t0 of the data file (if present)
|
||||
* - 'T' set t0 channel to the estimated t0
|
||||
* - 't' set t0 channel to the current cursor position
|
||||
* - 'b' set first background channel
|
||||
* - 'B' set last background channel
|
||||
* - 'd' set first good bin channel
|
||||
* - 'D' set last good bin channel
|
||||
* \brief Handles keyboard and mouse events for interactive t0/range selection.
|
||||
*
|
||||
* \param event event type
|
||||
* \param x keyboard event: character key; mouse event: x-position
|
||||
* \param y mouse event: y-position
|
||||
* \param selected not used
|
||||
* Processes keyboard commands for t0 determination and range selection.
|
||||
* Mouse position is tracked for bin selection. This is the main event
|
||||
* handler for the interactive GUI.
|
||||
*
|
||||
* \par Keyboard Commands:
|
||||
* - 'q': Close current canvas (local quit)
|
||||
* - 'Q': Quit entire application (global quit)
|
||||
* - 'u': Unzoom to original histogram range
|
||||
* - 'z': Zoom to region around t0
|
||||
* - 's': Toggle visibility of t0 from data file
|
||||
* - 'T': Set t0 to estimated value (maximum bin)
|
||||
* - 't': Set t0 to cursor position
|
||||
* - 'b': Set background start bin to cursor position
|
||||
* - 'B': Set background end bin to cursor position
|
||||
* - 'd': Set first good data bin to cursor position
|
||||
* - 'D': Set last good data bin to cursor position
|
||||
*
|
||||
* \param event Event type (kKeyPress for keyboard events)
|
||||
* \param x For keyboard: character key code; for mouse: x-position in pixels
|
||||
* \param y For mouse: y-position in pixels
|
||||
* \param selected Pointer to selected ROOT object (unused)
|
||||
*/
|
||||
void PMusrT0::HandleCmdKey(Int_t event, Int_t x, Int_t y, TObject *selected)
|
||||
{
|
||||
@@ -610,8 +625,10 @@ void PMusrT0::HandleCmdKey(Int_t event, Int_t x, Int_t y, TObject *selected)
|
||||
// Quit (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Slot called when the canvas is closed via the close icon (cross top right corner).
|
||||
* It is emitting a global quit singal.
|
||||
* \brief Slot called when canvas is closed via the close button.
|
||||
*
|
||||
* This method is invoked when the user clicks the close icon (X) in the
|
||||
* canvas window. It sets a global quit status and emits the Done signal.
|
||||
*/
|
||||
void PMusrT0::Quit()
|
||||
{
|
||||
@@ -623,9 +640,12 @@ void PMusrT0::Quit()
|
||||
// SetTimeout (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>
|
||||
* \brief Sets automatic timeout for the interactive session.
|
||||
*
|
||||
* \param timeout after which the done signal shall be emitted. Given in seconds
|
||||
* Creates and starts a timer that will automatically call Quit() if no
|
||||
* user interaction occurs within the specified timeout period.
|
||||
*
|
||||
* \param timeout Timeout duration in seconds (≤0 disables timeout)
|
||||
*/
|
||||
void PMusrT0::SetTimeout(Int_t timeout)
|
||||
{
|
||||
@@ -645,9 +665,12 @@ void PMusrT0::SetTimeout(Int_t timeout)
|
||||
// SetMsrHandler
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Set the msr-file handler
|
||||
* \brief Sets the MSR file handler for accessing run configuration.
|
||||
*
|
||||
* \param msrHandler msr-file handler pointer
|
||||
* The MSR handler provides access to run parameters, t0 values, and other
|
||||
* configuration data needed for interactive t0/range determination.
|
||||
*
|
||||
* \param msrHandler Pointer to initialized PMsrHandler instance
|
||||
*/
|
||||
void PMusrT0::SetMsrHandler(PMsrHandler *msrHandler)
|
||||
{
|
||||
@@ -658,7 +681,12 @@ void PMusrT0::SetMsrHandler(PMsrHandler *msrHandler)
|
||||
// InitT0
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Initialize t0 data.
|
||||
* \brief Initializes the interactive t0 determination GUI.
|
||||
*
|
||||
* Creates and displays the t0 marker line on the histogram canvas.
|
||||
* The initial t0 value is retrieved from the MSR file based on the
|
||||
* current detector tag (forward/backward) and histogram index.
|
||||
* The t0 line is drawn as a green vertical line from 0 to histogram maximum.
|
||||
*/
|
||||
void PMusrT0::InitT0()
|
||||
{
|
||||
@@ -699,7 +727,14 @@ void PMusrT0::InitT0()
|
||||
// InitDataAndBkg
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Initialize data and background ranges.
|
||||
* \brief Initializes the interactive data and background range GUI.
|
||||
*
|
||||
* Creates and displays data and background region histograms overlaid on
|
||||
* the main histogram. Retrieves initial range values from the MSR file
|
||||
* based on detector tag (forward/backward):
|
||||
* - Data region shown in blue (first good bin to last good bin)
|
||||
* - Background region shown in red (background start to end)
|
||||
* - Vertical lines mark the boundaries of both regions
|
||||
*/
|
||||
void PMusrT0::InitDataAndBkg()
|
||||
{
|
||||
@@ -795,7 +830,10 @@ void PMusrT0::InitDataAndBkg()
|
||||
// ShowDataFileT0Channel
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Show the t0 channel from the data file (if present).
|
||||
* \brief Displays the t0 value found in the data file.
|
||||
*
|
||||
* Creates and draws an orange vertical line showing the t0 value that was
|
||||
* read from the raw data file. This allows comparison with the user-selected t0.
|
||||
*/
|
||||
void PMusrT0::ShowDataFileT0Channel()
|
||||
{
|
||||
@@ -818,7 +856,10 @@ void PMusrT0::ShowDataFileT0Channel()
|
||||
// HideDataFileT0Channel
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Hide the t0 channel from the data file (if currently displayed).
|
||||
* \brief Hides the t0 value line from the data file.
|
||||
*
|
||||
* Removes the orange vertical line showing the data file t0 value.
|
||||
* The canvas is updated to reflect the change.
|
||||
*/
|
||||
void PMusrT0::HideDataFileT0Channel()
|
||||
{
|
||||
@@ -832,7 +873,11 @@ void PMusrT0::HideDataFileT0Channel()
|
||||
// SetT0Channel
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Set the t0 channel to the current cursor position and keep the x-position as new t0 bin.
|
||||
* \brief Sets t0 to the current cursor position.
|
||||
*
|
||||
* Converts cursor pixel position to bin number, updates the MSR handler
|
||||
* with the new t0 value, and moves the green t0 line to the cursor position.
|
||||
* The t0 index is calculated based on detector tag and fit type (single/asymmetry).
|
||||
*/
|
||||
void PMusrT0::SetT0Channel()
|
||||
{
|
||||
@@ -876,7 +921,11 @@ void PMusrT0::SetT0Channel()
|
||||
// SetEstimatedT0Channel
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Set the estimated t0 channel to the current cursor position and keep the x-position as new t0 bin.
|
||||
* \brief Sets t0 to the estimated value (maximum bin).
|
||||
*
|
||||
* Uses the automatically estimated t0 value (bin with maximum counts) as the
|
||||
* new t0. Updates the MSR handler and moves the green t0 line to the estimated
|
||||
* position. The t0 index is calculated based on detector tag and fit type.
|
||||
*/
|
||||
void PMusrT0::SetEstimatedT0Channel()
|
||||
{
|
||||
@@ -916,7 +965,11 @@ void PMusrT0::SetEstimatedT0Channel()
|
||||
// SetDataFirstChannel
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Set the first good data channel to the current cursor position and keep the x-position as new first good data bin.
|
||||
* \brief Sets the first good data bin to the cursor position.
|
||||
*
|
||||
* Converts cursor position to bin number, updates the MSR handler with the
|
||||
* new first good bin value, and redraws the blue data region histogram.
|
||||
* The blue vertical line marking the data start is moved to the new position.
|
||||
*/
|
||||
void PMusrT0::SetDataFirstChannel()
|
||||
{
|
||||
@@ -962,7 +1015,11 @@ void PMusrT0::SetDataFirstChannel()
|
||||
// SetDataLastChannel
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Set the last good data channel to the current cursor position and keep the x-position as new last good data bin.
|
||||
* \brief Sets the last good data bin to the cursor position.
|
||||
*
|
||||
* Converts cursor position to bin number, updates the MSR handler with the
|
||||
* new last good bin value, and redraws the blue data region histogram.
|
||||
* The blue vertical line marking the data end is moved to the new position.
|
||||
*/
|
||||
void PMusrT0::SetDataLastChannel()
|
||||
{
|
||||
@@ -1008,7 +1065,11 @@ void PMusrT0::SetDataLastChannel()
|
||||
// SetBkgFirstChannel
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Set the first background channel to the current cursor position and keep the x-position as new first background bin.
|
||||
* \brief Sets the background start bin to the cursor position.
|
||||
*
|
||||
* Converts cursor position to bin number, updates the MSR handler with the
|
||||
* new background start value, and redraws the red background region histogram.
|
||||
* The red vertical line marking the background start is moved to the new position.
|
||||
*/
|
||||
void PMusrT0::SetBkgFirstChannel()
|
||||
{
|
||||
@@ -1054,7 +1115,11 @@ void PMusrT0::SetBkgFirstChannel()
|
||||
// SetBkgLastChannel
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Set the last background channel to the current cursor position and keep the x-position as new last background bin.
|
||||
* \brief Sets the background end bin to the cursor position.
|
||||
*
|
||||
* Converts cursor position to bin number, updates the MSR handler with the
|
||||
* new background end value, and redraws the red background region histogram.
|
||||
* The red vertical line marking the background end is moved to the new position.
|
||||
*/
|
||||
void PMusrT0::SetBkgLastChannel()
|
||||
{
|
||||
@@ -1100,7 +1165,10 @@ void PMusrT0::SetBkgLastChannel()
|
||||
// UnZoom
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Unzoom the current histogram
|
||||
* \brief Resets zoom to show the full histogram range.
|
||||
*
|
||||
* Unzooms both x and y axes of the histogram to display the complete
|
||||
* data range. The canvas is updated to reflect the change.
|
||||
*/
|
||||
void PMusrT0::UnZoom()
|
||||
{
|
||||
@@ -1115,7 +1183,11 @@ void PMusrT0::UnZoom()
|
||||
// ZoomT0
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Zoom into the histogram region of the t0, and/or estimated t0 range.
|
||||
* \brief Zooms to the region around t0 for precise adjustment.
|
||||
*
|
||||
* Zooms the x-axis to a ±75 bin range centered on the current t0 position.
|
||||
* This allows for precise t0 selection. If t0 is near the histogram edges,
|
||||
* the zoom range is automatically adjusted to stay within valid bin numbers.
|
||||
*/
|
||||
void PMusrT0::ZoomT0()
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -35,7 +35,10 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor.
|
||||
* \brief Default constructor that initializes to default values.
|
||||
*
|
||||
* Sets background range to unused (-1, -1) and packing to 1 (no rebinning).
|
||||
* Background values and data must be set separately using setter methods.
|
||||
*/
|
||||
PPrepFourier::PPrepFourier()
|
||||
{
|
||||
@@ -48,7 +51,15 @@ PPrepFourier::PPrepFourier()
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor.
|
||||
* \brief Full constructor that initializes all configuration parameters.
|
||||
*
|
||||
* Creates a PPrepFourier instance with complete configuration. Background
|
||||
* can be specified either via range (for automatic calculation) or via
|
||||
* explicit values (one per data set to be added later).
|
||||
*
|
||||
* \param packing Rebinning factor (1=no rebinning, N=combine N bins)
|
||||
* \param bkgRange Background range [start, end] in bins (-1 if not used)
|
||||
* \param bkg Vector of explicit background values (one per data set)
|
||||
*/
|
||||
PPrepFourier::PPrepFourier(const Int_t packing, const Int_t *bkgRange, PDoubleVector bkg) :
|
||||
fPacking(packing)
|
||||
@@ -61,7 +72,10 @@ PPrepFourier::PPrepFourier(const Int_t packing, const Int_t *bkgRange, PDoubleVe
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor.
|
||||
* \brief Destructor that cleans up internal data structures.
|
||||
*
|
||||
* Clears both raw data and processed data vectors. Note that TH1F objects
|
||||
* returned by GetData() are owned by the caller and not cleaned up here.
|
||||
*/
|
||||
PPrepFourier::~PPrepFourier()
|
||||
{
|
||||
@@ -73,9 +87,14 @@ PPrepFourier::~PPrepFourier()
|
||||
// SetBkgRange
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>set the background range.
|
||||
* \brief Sets the background range for automatic background calculation.
|
||||
*
|
||||
* \param bkgRange array with background range
|
||||
* Specifies the bin range [start, end] for calculating background by averaging.
|
||||
* Values of -1 indicate that background range is not used (explicit background
|
||||
* values should be provided instead). Validates that both values are ≥-1 and
|
||||
* prints warnings if invalid values are encountered.
|
||||
*
|
||||
* \param bkgRange Array [start, end] with background bin range (both must be ≥-1)
|
||||
*/
|
||||
void PPrepFourier::SetBkgRange(const Int_t *bkgRange)
|
||||
{
|
||||
@@ -116,12 +135,16 @@ void PPrepFourier::SetBkgRange(const Int_t *bkgRange)
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// SetBkgRange
|
||||
// SetBkg
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>set the background values for all the histos.
|
||||
* \brief Sets explicit background values for all data sets.
|
||||
*
|
||||
* \param bkg vector
|
||||
* Provides pre-calculated background values (one per data set) instead of
|
||||
* calculating them from a background range. This allows different background
|
||||
* values for each histogram.
|
||||
*
|
||||
* \param bkg Vector of background values (should match number of data sets)
|
||||
*/
|
||||
void PPrepFourier::SetBkg(PDoubleVector bkg)
|
||||
{
|
||||
@@ -133,9 +156,13 @@ void PPrepFourier::SetBkg(PDoubleVector bkg)
|
||||
// SetPacking
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>set the packing for the histograms.
|
||||
* \brief Sets the rebinning/packing factor for data reduction.
|
||||
*
|
||||
* \param packing number to be used.
|
||||
* Specifies how many adjacent bins to combine during DoPacking(). A value
|
||||
* of 1 means no rebinning, 2 combines pairs of bins, etc. Invalid values
|
||||
* (≤0) are rejected with a warning.
|
||||
*
|
||||
* \param packing Number of bins to combine (must be > 0)
|
||||
*/
|
||||
void PPrepFourier::SetPacking(const Int_t packing)
|
||||
{
|
||||
@@ -150,10 +177,13 @@ void PPrepFourier::SetPacking(const Int_t packing)
|
||||
// AddData
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>add a data-set (time domain data + meta information) to the internal
|
||||
* data vector.
|
||||
* \brief Adds a time-domain data set to the internal collection.
|
||||
*
|
||||
* \param data set to be added
|
||||
* Stores the raw data and metadata for later processing. Multiple data sets
|
||||
* can be added and will be processed together by DoBkgCorrection(), DoPacking(),
|
||||
* and DoLifeTimeCorrection().
|
||||
*
|
||||
* \param data musrFT_data structure containing raw histogram data and metadata
|
||||
*/
|
||||
void PPrepFourier::AddData(musrFT_data &data)
|
||||
{
|
||||
@@ -164,7 +194,17 @@ void PPrepFourier::AddData(musrFT_data &data)
|
||||
// DoBkgCorrection
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Correct the internal data sets according to a background interval given.
|
||||
* \brief Applies background correction to all data sets.
|
||||
*
|
||||
* Subtracts background from each data point. The background can be specified
|
||||
* in two ways:
|
||||
* 1. Background range: Calculates average over the specified bin range
|
||||
* 2. Explicit values: Uses the background values set via SetBkg()
|
||||
*
|
||||
* If fData is not yet initialized, calls InitData() first. If neither
|
||||
* background range nor explicit values are provided, no correction is applied.
|
||||
* Validates that background range is within data bounds and that the number
|
||||
* of explicit background values matches the number of data sets.
|
||||
*/
|
||||
void PPrepFourier::DoBkgCorrection()
|
||||
{
|
||||
@@ -221,7 +261,14 @@ void PPrepFourier::DoBkgCorrection()
|
||||
// DoPacking
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Rebin (pack) the internal data.
|
||||
* \brief Applies rebinning/packing to reduce the number of data points.
|
||||
*
|
||||
* Combines adjacent bins according to the packing factor to improve statistics
|
||||
* and reduce data size. Bins are summed in groups of fPacking size. If
|
||||
* fPacking=1, no rebinning is performed.
|
||||
*
|
||||
* If fData is not yet initialized, calls InitData() first. The time resolution
|
||||
* should be adjusted accordingly (multiplied by fPacking) when creating histograms.
|
||||
*/
|
||||
void PPrepFourier::DoPacking()
|
||||
{
|
||||
@@ -256,11 +303,21 @@ void PPrepFourier::DoPacking()
|
||||
// DoLifeTimeCorrection
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Try to do a muon life time correction. The idea is to estimate N0 without
|
||||
* any theory. This will be OK for high fields (> couple kGauss) but not so good
|
||||
* for low fields.
|
||||
* \brief Applies muon lifetime correction for theory-free Fourier analysis.
|
||||
*
|
||||
* \param fudge rescaling factor for the estimated N0. Should be around 1
|
||||
* Performs a theory-free lifetime correction by:
|
||||
* 1. Multiplying data by exp(t/τ_μ) to remove muon decay
|
||||
* 2. Estimating N0 as the average of the corrected data
|
||||
* 3. Subtracting N0 and normalizing by N0 to get asymmetry-like data
|
||||
*
|
||||
* This approach works well for high fields (>few kGauss) where depolarization
|
||||
* is minimal, but may be less accurate for low fields where significant
|
||||
* relaxation occurs during the muon lifetime.
|
||||
*
|
||||
* If fData is not yet initialized, calls InitData() first. Background correction
|
||||
* should typically be applied before lifetime correction.
|
||||
*
|
||||
* \param fudge Rescaling factor for estimated N0 (typically ~1.0, allows fine-tuning)
|
||||
*/
|
||||
void PPrepFourier::DoLifeTimeCorrection(Double_t fudge)
|
||||
{
|
||||
@@ -299,9 +356,10 @@ void PPrepFourier::DoLifeTimeCorrection(Double_t fudge)
|
||||
// GetInfo
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Returns the meta information of a data set.
|
||||
* \brief Returns the metadata string for a specific data set.
|
||||
*
|
||||
* \param idx index of the object
|
||||
* \param idx Data set index
|
||||
* \return Metadata string from musrFT_data.info, or empty string if idx out of range
|
||||
*/
|
||||
TString PPrepFourier::GetInfo(const UInt_t idx)
|
||||
{
|
||||
@@ -317,9 +375,13 @@ TString PPrepFourier::GetInfo(const UInt_t idx)
|
||||
// GetDataSetTag
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Returns the data set tag of the object
|
||||
* \brief Returns the data set tag identifier.
|
||||
*
|
||||
* \param idx index of the object
|
||||
* The data set tag is used to label and group related data sets, particularly
|
||||
* for average-per-data-set operations in Fourier analysis.
|
||||
*
|
||||
* \param idx Data set index
|
||||
* \return Data set tag value, or -1 if idx out of range
|
||||
*/
|
||||
Int_t PPrepFourier::GetDataSetTag(const UInt_t idx)
|
||||
{
|
||||
@@ -335,8 +397,16 @@ Int_t PPrepFourier::GetDataSetTag(const UInt_t idx)
|
||||
// GetData
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Creates the requested TH1F objects and returns them. The ownership is with
|
||||
* the caller.
|
||||
* \brief Creates ROOT histograms for all processed data sets.
|
||||
*
|
||||
* Converts the processed data into TH1F histograms with proper time binning.
|
||||
* The time range, bin width, and histogram titles are taken from the
|
||||
* musrFT_data metadata. The packing factor is applied to the time resolution.
|
||||
*
|
||||
* \return Vector of TH1F pointers (caller owns and must delete)
|
||||
*
|
||||
* \note The caller is responsible for deleting the returned histograms.
|
||||
* \note Returns empty vector if no data is present.
|
||||
*/
|
||||
std::vector<TH1F*> PPrepFourier::GetData()
|
||||
{
|
||||
@@ -402,10 +472,18 @@ std::vector<TH1F*> PPrepFourier::GetData()
|
||||
// GetData
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Creates the requested TH1F object and returns it. The ownership is with
|
||||
* the caller.
|
||||
* \brief Creates a ROOT histogram for a specific processed data set.
|
||||
*
|
||||
* \param idx index of the requested histogram
|
||||
* Converts a single processed data set into a TH1F histogram with proper
|
||||
* time binning. The time range, bin width, and histogram title are taken
|
||||
* from the musrFT_data metadata. The packing factor is applied to the
|
||||
* time resolution.
|
||||
*
|
||||
* \param idx Data set index
|
||||
* \return TH1F pointer (caller owns and must delete), or nullptr if idx out of range
|
||||
*
|
||||
* \note The caller is responsible for deleting the returned histogram.
|
||||
* \note Returns nullptr if no data is present or idx is out of range.
|
||||
*/
|
||||
TH1F *PPrepFourier::GetData(const UInt_t idx)
|
||||
{
|
||||
@@ -458,7 +536,14 @@ TH1F *PPrepFourier::GetData(const UInt_t idx)
|
||||
// InitData (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Copy raw-data to internal data from t0 to the size of raw-data.
|
||||
* \brief Initializes processed data by copying from raw data starting at t0.
|
||||
*
|
||||
* Creates the fData vectors from fRawData, starting from the t0 bin for each
|
||||
* data set. This effectively removes pre-t0 bins and creates a working copy
|
||||
* for subsequent processing (background correction, packing, lifetime correction).
|
||||
*
|
||||
* If t0 is negative or not set, data is copied from bin 0. This method is
|
||||
* called automatically by processing methods if fData is not yet initialized.
|
||||
*/
|
||||
void PPrepFourier::InitData()
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
@@ -45,7 +46,10 @@ ClassImpQ(PXmlRgeHandler)
|
||||
// OnStartDocument
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called on start of the XML file reading. Initializes all necessary variables.
|
||||
* \brief SAX callback invoked at the start of XML document parsing.
|
||||
*
|
||||
* Initializes the parsing state by resetting the key to empty. This ensures
|
||||
* clean state for processing the XML content.
|
||||
*/
|
||||
void PXmlRgeHandler::OnStartDocument()
|
||||
{
|
||||
@@ -56,7 +60,14 @@ void PXmlRgeHandler::OnStartDocument()
|
||||
// OnEndDocument
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called on end of XML file reading.
|
||||
* \brief SAX callback invoked at the end of XML document parsing.
|
||||
*
|
||||
* Performs final validation to ensure all required fields were parsed:
|
||||
* - TrimSP data path must be set
|
||||
* - RGE filename prefix must be set
|
||||
* - At least one implantation energy must be specified
|
||||
*
|
||||
* Sets fIsValid to false and calls OnError() if any validation fails.
|
||||
*/
|
||||
void PXmlRgeHandler::OnEndDocument()
|
||||
{
|
||||
@@ -85,11 +96,19 @@ void PXmlRgeHandler::OnEndDocument()
|
||||
// OnStartElement
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when a XML start element is found. Filters out the needed elements
|
||||
* and sets a proper key.
|
||||
* \brief SAX callback invoked when an XML start tag is encountered.
|
||||
*
|
||||
* Processes recognized elements within the <trim_sp> section:
|
||||
* - <data_path>: Directory containing RGE files
|
||||
* - <rge_fln_pre>: RGE filename prefix
|
||||
* - <energy>: Single implantation energy value
|
||||
* - <energy_vect>: Energy range with start/stop/step attributes
|
||||
*
|
||||
* For <energy_vect>, parses the attributes and generates the energy list.
|
||||
* Performs extensive validation on attribute values and ranges.
|
||||
*
|
||||
* \param str XML element name
|
||||
* \param attributes used only for energy_vect
|
||||
* \param attributes Element attributes (only used for energy_vect)
|
||||
*/
|
||||
void PXmlRgeHandler::OnStartElement(const Char_t *str, const TList *attributes)
|
||||
{
|
||||
@@ -182,9 +201,12 @@ void PXmlRgeHandler::OnStartElement(const Char_t *str, const TList *attributes)
|
||||
// OnEndElement
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when a XML end element is found. Resets the handler key.
|
||||
* \brief SAX callback invoked when an XML end tag is encountered.
|
||||
*
|
||||
* \param str not used
|
||||
* Resets the parsing state when leaving the <trim_sp> section and
|
||||
* clears the current element key for all end tags.
|
||||
*
|
||||
* \param str XML element name
|
||||
*/
|
||||
void PXmlRgeHandler::OnEndElement(const Char_t *str)
|
||||
{
|
||||
@@ -199,10 +221,17 @@ void PXmlRgeHandler::OnEndElement(const Char_t *str)
|
||||
// OnCharacters
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Content of a given XML element. Filters out the data and feeds them to
|
||||
* the internal variables.
|
||||
* \brief SAX callback invoked for text content between XML tags.
|
||||
*
|
||||
* \param str XML element string
|
||||
* Processes the content based on the current parsing state (fKey):
|
||||
* - eDataPath: Stores the data directory path
|
||||
* - eFlnPre: Stores the RGE filename prefix
|
||||
* - eEnergy: Parses integer energy value and adds to energy list
|
||||
*
|
||||
* Performs validation and error handling for energy values, ensuring
|
||||
* they are valid integers within range.
|
||||
*
|
||||
* \param str Text content from XML element
|
||||
*/
|
||||
void PXmlRgeHandler::OnCharacters(const Char_t *str)
|
||||
{
|
||||
@@ -249,9 +278,11 @@ void PXmlRgeHandler::OnCharacters(const Char_t *str)
|
||||
// OnComment
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when a XML comment is found. Not used.
|
||||
* \brief SAX callback invoked for XML comments.
|
||||
*
|
||||
* \param str not used.
|
||||
* Currently not used - comments are ignored.
|
||||
*
|
||||
* \param str Comment text
|
||||
*/
|
||||
void PXmlRgeHandler::OnComment(const Char_t *str)
|
||||
{
|
||||
@@ -262,9 +293,11 @@ void PXmlRgeHandler::OnComment(const Char_t *str)
|
||||
// OnWarning
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when the XML parser emits a warning.
|
||||
* \brief SAX callback invoked when the parser emits a warning.
|
||||
*
|
||||
* \param str warning string
|
||||
* Prints warning message to stderr.
|
||||
*
|
||||
* \param str Warning message from parser
|
||||
*/
|
||||
void PXmlRgeHandler::OnWarning(const Char_t *str)
|
||||
{
|
||||
@@ -276,9 +309,12 @@ void PXmlRgeHandler::OnWarning(const Char_t *str)
|
||||
// OnError
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when the XML parser emits an error.
|
||||
* \brief SAX callback invoked when the parser encounters an error.
|
||||
*
|
||||
* \param str error string
|
||||
* Prints error message to stderr. Called both by the parser and
|
||||
* by this handler's own validation code.
|
||||
*
|
||||
* \param str Error message
|
||||
*/
|
||||
void PXmlRgeHandler::OnError(const Char_t *str)
|
||||
{
|
||||
@@ -290,9 +326,11 @@ void PXmlRgeHandler::OnError(const Char_t *str)
|
||||
// OnFatalError
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when the XML parser emits a fatal error.
|
||||
* \brief SAX callback invoked when the parser encounters a fatal error.
|
||||
*
|
||||
* \param str fatal error string
|
||||
* Prints fatal error message to stderr. Fatal errors typically stop parsing.
|
||||
*
|
||||
* \param str Fatal error message
|
||||
*/
|
||||
void PXmlRgeHandler::OnFatalError(const Char_t *str)
|
||||
{
|
||||
@@ -304,10 +342,12 @@ void PXmlRgeHandler::OnFatalError(const Char_t *str)
|
||||
// OnCdataBlock
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Not used.
|
||||
* \brief SAX callback invoked for CDATA blocks.
|
||||
*
|
||||
* \param str not used
|
||||
* \param len not used
|
||||
* Currently not used - CDATA blocks are ignored.
|
||||
*
|
||||
* \param str CDATA content
|
||||
* \param len Length of CDATA content
|
||||
*/
|
||||
void PXmlRgeHandler::OnCdataBlock(const Char_t *str, Int_t len)
|
||||
{
|
||||
@@ -322,8 +362,18 @@ ClassImp(PRgeHandler)
|
||||
// Ctor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief PRgeHandler::PRgeHandler
|
||||
* @param fln
|
||||
* \brief Constructor that loads TrimSP range distribution data.
|
||||
*
|
||||
* Performs the following steps:
|
||||
* 1. Validates that XML configuration filename is provided
|
||||
* 2. Parses XML file using PXmlRgeHandler to get file paths and energies
|
||||
* 3. Reads all specified .rge files from TrimSP
|
||||
* 4. Calculates total particle counts for each energy
|
||||
* 5. Computes normalized distributions nn(z) where ∫nn(z)dz = 1
|
||||
*
|
||||
* Sets fValid to false if any errors occur during loading.
|
||||
*
|
||||
* \param fln Path to XML configuration file (empty triggers error)
|
||||
*/
|
||||
PRgeHandler::PRgeHandler(const std::string fln)
|
||||
{
|
||||
@@ -440,10 +490,18 @@ PRgeHandler::PRgeHandler(const std::string fln)
|
||||
// ReadRgeFile
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Read the content of a rge-file.
|
||||
* \brief Reads a single TrimSP .rge file and populates a PRgeData structure.
|
||||
*
|
||||
* @param fln file name of the rge-file
|
||||
* @return true on success.
|
||||
* Parses the two-column format from TrimSP output:
|
||||
* - Column 1: Depth in Ångström (converted to nm by dividing by 10)
|
||||
* - Column 2: Number of particles (amplitude)
|
||||
*
|
||||
* Skips empty lines and non-numeric lines. Performs extensive validation
|
||||
* on numeric values with detailed error messages.
|
||||
*
|
||||
* \param fln Path to the .rge file
|
||||
* \param data PRgeData structure to populate with depth and amplitude vectors
|
||||
* \return True on success, false if file cannot be opened or contains invalid data
|
||||
*/
|
||||
bool PRgeHandler::ReadRgeFile(const std::string fln, PRgeData &data)
|
||||
{
|
||||
@@ -553,10 +611,13 @@ bool PRgeHandler::ReadRgeFile(const std::string fln, PRgeData &data)
|
||||
// GetZmax via energy
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get maximal depth for a given energy.
|
||||
* \brief Returns maximum penetration depth for a given implantation energy.
|
||||
*
|
||||
* @param energy energy in (eV)
|
||||
* @return zMax if energy is found, -1 otherwise.
|
||||
* Searches for a data set matching the specified energy (within 0.9 keV
|
||||
* tolerance) and returns its maximum depth value.
|
||||
*
|
||||
* \param energy Implantation energy in eV
|
||||
* \return Maximum depth in nm, or -1 if energy not found
|
||||
*/
|
||||
Double_t PRgeHandler::GetZmax(const Double_t energy)
|
||||
{
|
||||
@@ -567,7 +628,7 @@ Double_t PRgeHandler::GetZmax(const Double_t energy)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (idx != -1)
|
||||
return GetZmax(idx);
|
||||
|
||||
@@ -578,10 +639,13 @@ Double_t PRgeHandler::GetZmax(const Double_t energy)
|
||||
// GetZmax via index
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get maximal depth for a given index.
|
||||
* \brief Returns maximum penetration depth for a given data set index.
|
||||
*
|
||||
* @param idx index for which zMax is requested.
|
||||
* @return zMax if idx is in range, -1 otherwise.
|
||||
* Returns the last depth value from the depth vector, which represents
|
||||
* the maximum penetration depth for this energy.
|
||||
*
|
||||
* \param idx Data set index (0 to GetNoOfRgeDataSets()-1)
|
||||
* \return Maximum depth in nm, or -1 if idx out of range
|
||||
*/
|
||||
Double_t PRgeHandler::GetZmax(const Int_t idx)
|
||||
{
|
||||
@@ -595,11 +659,14 @@ Double_t PRgeHandler::GetZmax(const Int_t idx)
|
||||
// Get_n via energy
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the normalized n(E,z) value.
|
||||
* \brief Returns normalized particle distribution at given energy and depth.
|
||||
*
|
||||
* @param energy (eV)
|
||||
* @param z (nm)
|
||||
* @return n(E,z) if energy and z are in proper range, -1.0 otherwise.
|
||||
* Searches for a data set matching the specified energy (within 0.9 keV
|
||||
* tolerance) and returns the normalized distribution value at depth z.
|
||||
*
|
||||
* \param energy Implantation energy in eV
|
||||
* \param z Depth in nm
|
||||
* \return Normalized distribution nn(E,z), or 0.0 if energy not found or z out of range
|
||||
*/
|
||||
Double_t PRgeHandler::Get_n(const Double_t energy, const Double_t z)
|
||||
{
|
||||
@@ -620,11 +687,17 @@ Double_t PRgeHandler::Get_n(const Double_t energy, const Double_t z)
|
||||
// Get_n via index
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the normalized n(idx,z) value.
|
||||
* \brief Returns normalized particle distribution at given index and depth.
|
||||
*
|
||||
* @param idx index of the rge-dataset
|
||||
* @param z (nm)
|
||||
* @return n(idx,z) if idx and z are in proper range, -1.0 otherwise.
|
||||
* Uses linear interpolation between adjacent data points to compute the
|
||||
* distribution value at the requested depth. The normalization ensures
|
||||
* that ∫nn(z)dz = 1 over the entire depth range.
|
||||
*
|
||||
* Special handling for z near zero: extrapolates linearly from first data point.
|
||||
*
|
||||
* \param idx Data set index (0 to GetNoOfRgeDataSets()-1)
|
||||
* \param z Depth in nm
|
||||
* \return Normalized distribution nn(idx,z), or 0.0 if idx or z out of range
|
||||
*/
|
||||
Double_t PRgeHandler::Get_n(const Int_t idx, const Double_t z)
|
||||
{
|
||||
@@ -658,10 +731,13 @@ Double_t PRgeHandler::Get_n(const Int_t idx, const Double_t z)
|
||||
// GetEnergyIndex
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the energy index by providing an energy in (eV).
|
||||
* \brief Finds the data set index corresponding to a given implantation energy.
|
||||
*
|
||||
* @param energy in (eV).
|
||||
* @return energy index if energy was found, -1 otherwise.
|
||||
* Searches through loaded data sets for a matching energy value using a
|
||||
* tolerance of 0.9 keV (i.e., |E_data - E_query| < 0.9 keV).
|
||||
*
|
||||
* \param energy Implantation energy in eV
|
||||
* \return Data set index (0 to GetNoOfRgeDataSets()-1), or -1 if not found
|
||||
*/
|
||||
Int_t PRgeHandler::GetEnergyIndex(const Double_t energy)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -50,7 +50,11 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Default constructor that initializes all member variables.
|
||||
*
|
||||
* Sets all counters and indices to default/invalid values. This constructor
|
||||
* creates an invalid instance that requires proper initialization via the
|
||||
* main constructor.
|
||||
*/
|
||||
PRunAsymmetry::PRunAsymmetry() : PRunBase()
|
||||
{
|
||||
@@ -71,12 +75,26 @@ PRunAsymmetry::PRunAsymmetry() : PRunBase()
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Main constructor that initializes μSR asymmetry fitting.
|
||||
*
|
||||
* \param msrInfo pointer to the msr-file handler
|
||||
* \param rawData raw run data
|
||||
* \param runNo number of the run within the msr-file
|
||||
* \param tag tag showing what shall be done: kFit == fitting, kView == viewing
|
||||
* Performs comprehensive initialization:
|
||||
* 1. Validates packing parameter from RUN or GLOBAL block
|
||||
* 2. Validates α parameter (required for asymmetry)
|
||||
* 3. Validates β parameter (optional, defaults to 1)
|
||||
* 4. Determines α/β configuration tag (1-4)
|
||||
* 5. Calls PrepareData() to load and process histogram data
|
||||
*
|
||||
* The α/β tag determines the asymmetry calculation method:
|
||||
* - Tag 1: α=1, β=1 (no corrections)
|
||||
* - Tag 2: α≠1, β=1 (forward/backward correction)
|
||||
* - Tag 3: α=1, β≠1 (alternative correction)
|
||||
* - Tag 4: α≠1, β≠1 (both corrections)
|
||||
*
|
||||
* \param msrInfo Pointer to MSR file handler
|
||||
* \param rawData Pointer to raw run data handler
|
||||
* \param runNo Run number within the MSR file
|
||||
* \param tag Operation mode (kFit or kView)
|
||||
* \param theoAsData If true, calculate theory only at data points
|
||||
*/
|
||||
PRunAsymmetry::PRunAsymmetry(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t runNo, EPMusrHandleTag tag, Bool_t theoAsData) :
|
||||
PRunBase(msrInfo, rawData, runNo, tag), fTheoAsData(theoAsData)
|
||||
@@ -173,7 +191,10 @@ PRunAsymmetry::PRunAsymmetry(PMsrHandler *msrInfo, PRunDataHandler *rawData, UIn
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor.
|
||||
* \brief Destructor that cleans up histogram data.
|
||||
*
|
||||
* Clears all four histogram vectors (forward/backward × data/errors)
|
||||
* to free memory.
|
||||
*/
|
||||
PRunAsymmetry::~PRunAsymmetry()
|
||||
{
|
||||
@@ -187,12 +208,21 @@ PRunAsymmetry::~PRunAsymmetry()
|
||||
// CalcChiSquare (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate chi-square.
|
||||
* \brief Calculates chi-square for μSR asymmetry fit.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value
|
||||
* Computes χ² by comparing the measured asymmetry with theory:
|
||||
* χ² = Σ[(A_data - A_theory)²/σ²]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* The asymmetry calculation depends on fAlphaBetaTag:
|
||||
* - Tag 1 (α=β=1): A = (F - B)/(F + B)
|
||||
* - Tag 2 (α≠1, β=1): A = (F - αB)/(F + αB)
|
||||
* - Tag 3 (α=1, β≠1): Uses β correction
|
||||
* - Tag 4 (α≠1, β≠1): Uses both α and β corrections
|
||||
*
|
||||
* Supports OpenMP parallelization for faster calculation.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT minimizer
|
||||
* \return Chi-square value
|
||||
*/
|
||||
Double_t PRunAsymmetry::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -289,12 +319,17 @@ Double_t PRunAsymmetry::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
// CalcChiSquareExpected (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate expected chi-square. Currently not implemented since not clear what to be done.
|
||||
* \brief Calculates expected chi-square value.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value == 0.0
|
||||
* This function is currently not implemented for asymmetry fits because the expected
|
||||
* chi-square calculation for asymmetry data requires a more complex statistical treatment
|
||||
* than for single histogram fits. The asymmetry is a ratio of count rates, and the
|
||||
* proper expected value calculation is non-trivial.
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* \param par Parameter vector from MINUIT minimizer
|
||||
* \return Always returns 0.0 (placeholder value)
|
||||
*
|
||||
* \todo Implement proper expected chi-square calculation for asymmetry fits
|
||||
*/
|
||||
Double_t PRunAsymmetry::CalcChiSquareExpected(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -305,9 +340,16 @@ Double_t PRunAsymmetry::CalcChiSquareExpected(const std::vector<Double_t>& par)
|
||||
// CalcMaxLikelihood (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>NOT IMPLEMENTED!!
|
||||
* \brief Calculates maximum likelihood estimator for asymmetry fit.
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* Maximum likelihood estimation provides an alternative to χ² minimization and can be
|
||||
* more appropriate for low-count data where Gaussian statistics do not apply. However,
|
||||
* the proper likelihood function for μSR asymmetry data is complex and not yet implemented.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT minimizer
|
||||
* \return Placeholder value of 1.0
|
||||
*
|
||||
* \todo Implement proper Poisson-based maximum likelihood for asymmetry fits
|
||||
*/
|
||||
Double_t PRunAsymmetry::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -320,9 +362,13 @@ Double_t PRunAsymmetry::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
// GetNoOfFitBins (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the number of fitted bins for the current fit range.
|
||||
* \brief Returns the number of bins included in the fit.
|
||||
*
|
||||
* <b>return:</b> number of fitted bins.
|
||||
* Calculates and returns the number of data bins that fall within the current fit range.
|
||||
* This value is used for determining degrees of freedom and is recalculated when the
|
||||
* fit range changes (e.g., via COMMAND block).
|
||||
*
|
||||
* \return Number of data bins included in the fit
|
||||
*/
|
||||
UInt_t PRunAsymmetry::GetNoOfFitBins()
|
||||
{
|
||||
@@ -335,15 +381,26 @@ UInt_t PRunAsymmetry::GetNoOfFitBins()
|
||||
// SetFitRangeBin (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Allows to change the fit range on the fly. Used in the COMMAND block.
|
||||
* The syntax of the string is: FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]].
|
||||
* If only one pair of fgb/lgb is given, it is used for all runs in the RUN block section.
|
||||
* If multiple fgb/lgb's are given, the number N has to be the number of RUN blocks in
|
||||
* the msr-file.
|
||||
* \brief Dynamically changes the fit range in bin units.
|
||||
*
|
||||
* <p>nXY are offsets which can be used to shift, limit the fit range.
|
||||
* Allows modification of the fit range at runtime, typically called from the COMMAND block.
|
||||
* Supports bin-based fit ranges with optional offsets for fine-tuning.
|
||||
*
|
||||
* \param fitRange string containing the necessary information.
|
||||
* Syntax formats:
|
||||
* - Single range: FIT_RANGE fgb[+n0] lgb[-n1]
|
||||
* - Applied to all RUN blocks
|
||||
* - Multiple ranges: FIT_RANGE fgb[+n00] lgb[-n01] fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]
|
||||
* - One pair per RUN block (N must equal number of RUN blocks)
|
||||
*
|
||||
* Parameters:
|
||||
* - fgb: First good bin (start of fit range)
|
||||
* - lgb: Last good bin (end of fit range)
|
||||
* - +n: Positive offset to shift start forward
|
||||
* - -n: Negative offset to shift end backward
|
||||
*
|
||||
* Example: "FIT_RANGE 10+5 200-10" uses bins [15, 190] for fitting
|
||||
*
|
||||
* \param fitRange String containing fit range specification
|
||||
*/
|
||||
void PRunAsymmetry::SetFitRangeBin(const TString fitRange)
|
||||
{
|
||||
@@ -425,7 +482,16 @@ void PRunAsymmetry::SetFitRangeBin(const TString fitRange)
|
||||
// CalcNoOfFitBins (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the number of fitted bins for the current fit range.
|
||||
* \brief Calculates the number of bins included in the current fit range.
|
||||
*
|
||||
* Determines fStartTimeBin and fEndTimeBin from the fit time range (fFitStartTime, fFitEndTime)
|
||||
* and data time grid. Ensures that bin indices remain within valid histogram bounds.
|
||||
* The result is stored in fNoOfFitBins.
|
||||
*
|
||||
* This calculation accounts for:
|
||||
* - Data time step and start time
|
||||
* - Rounding effects (ceiling for start, floor for end)
|
||||
* - Boundary conditions (clips to [0, histogram size])
|
||||
*/
|
||||
void PRunAsymmetry::CalcNoOfFitBins()
|
||||
{
|
||||
@@ -447,7 +513,20 @@ void PRunAsymmetry::CalcNoOfFitBins()
|
||||
// CalcTheory (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate theory for a given set of fit-parameters.
|
||||
* \brief Calculates theoretical asymmetry values for the current parameters.
|
||||
*
|
||||
* Computes the expected asymmetry A(t) for all data points based on the current
|
||||
* parameter values and the user-defined theory function. The calculation depends
|
||||
* on the α/β correction mode:
|
||||
*
|
||||
* - Tag 1 (α=1, β=1): A(t) = f(t)
|
||||
* - Tag 2 (α≠1, β=1): A(t) = [f(t)(α+1) - (α-1)] / [(α+1) - f(t)(α-1)]
|
||||
* - Tag 3 (α=1, β≠1): A(t) = f(t)(β+1) / [2 - f(t)(β-1)]
|
||||
* - Tag 4 (α≠1, β≠1): Combined α and β corrections
|
||||
*
|
||||
* where f(t) is the raw theory function from the THEORY block.
|
||||
*
|
||||
* The calculated values are stored in fData for plotting and comparison with measured data.
|
||||
*/
|
||||
void PRunAsymmetry::CalcTheory()
|
||||
{
|
||||
@@ -531,23 +610,31 @@ void PRunAsymmetry::CalcTheory()
|
||||
// PrepareData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Prepare data for fitting or viewing. What is already processed at this stage:
|
||||
* - get all needed forward/backward histograms
|
||||
* - get time resolution
|
||||
* - get start/stop fit time
|
||||
* - get t0's and perform necessary cross checks (e.g. if t0 of msr-file (if present) are consistent with t0 of the data files, etc.)
|
||||
* - add runs (if addruns are present)
|
||||
* - group histograms (if grouping is present)
|
||||
* - subtract background
|
||||
* \brief Main data preparation routine for asymmetry fitting and viewing.
|
||||
*
|
||||
* Error propagation for \f$ A_i = (f_i^{\rm c}-b_i^{\rm c})/(f_i^{\rm c}+b_i^{\rm c})\f$:
|
||||
* \f[ \Delta A_i = \pm\frac{2}{(f_i^{\rm c}+b_i^{\rm c})^2}\left[
|
||||
* (b_i^{\rm c})^2 (\Delta f_i^{\rm c})^2 +
|
||||
* (\Delta b_i^{\rm c})^2 (f_i^{\rm c})^2\right]^{1/2}\f]
|
||||
* Performs comprehensive data preparation including:
|
||||
* - Loading forward/backward histograms from data files
|
||||
* - Extracting metadata (field, energy, temperature)
|
||||
* - Determining time resolution from data file
|
||||
* - Validating and retrieving t0 values for all histograms
|
||||
* - Adding multiple runs together (if addruns are specified)
|
||||
* - Grouping multiple histograms (if grouping is specified)
|
||||
* - Subtracting background (fixed or estimated)
|
||||
* - Calculating asymmetry and error bars
|
||||
* - Applying bin packing (if specified)
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if everthing went smooth
|
||||
* - false, otherwise.
|
||||
* The asymmetry is calculated as:
|
||||
* \f[ A_i = \frac{f_i^{\rm c} - b_i^{\rm c}}{f_i^{\rm c} + b_i^{\rm c}} \f]
|
||||
*
|
||||
* Error propagation (assuming Poisson statistics):
|
||||
* \f[ \Delta A_i = \pm\frac{2}{(f_i^{\rm c}+b_i^{\rm c})^2}\sqrt{
|
||||
* (b_i^{\rm c})^2 (\Delta f_i^{\rm c})^2 +
|
||||
* (f_i^{\rm c})^2 (\Delta b_i^{\rm c})^2} \f]
|
||||
*
|
||||
* where \f$ f_i^{\rm c} \f$ and \f$ b_i^{\rm c} \f$ are background-corrected forward and
|
||||
* backward histograms, respectively.
|
||||
*
|
||||
* \return True if data preparation succeeds, false on any error
|
||||
*/
|
||||
Bool_t PRunAsymmetry::PrepareData()
|
||||
{
|
||||
@@ -625,16 +712,26 @@ Bool_t PRunAsymmetry::PrepareData()
|
||||
forward[i].resize(runData->GetDataBin(forwardHistoNo[i])->size());
|
||||
forward[i] = *runData->GetDataBin(forwardHistoNo[i]);
|
||||
}
|
||||
// check if a dead time correction has to be done
|
||||
// this will be done automatically in the function itself, which also
|
||||
// checks in the global and run section
|
||||
DeadTimeCorrection(forward, forwardHistoNo);
|
||||
|
||||
backward.resize(backwardHistoNo.size()); // resize to number of groups
|
||||
for (UInt_t i=0; i<backwardHistoNo.size(); i++) {
|
||||
backward[i].resize(runData->GetDataBin(backwardHistoNo[i])->size());
|
||||
backward[i] = *runData->GetDataBin(backwardHistoNo[i]);
|
||||
}
|
||||
// check if a dead time correction has to be done
|
||||
// this will be done automatically in the function itself, which also
|
||||
// checks in the global and run section
|
||||
DeadTimeCorrection(backward, backwardHistoNo);
|
||||
|
||||
// check if addrun's are present, and if yes add data
|
||||
// check if there are runs to be added to the current one
|
||||
if (fRunInfo->GetRunNameSize() > 1) { // runs to be added present
|
||||
PRawRunData *addRunData;
|
||||
std::vector<PDoubleVector> addForward, addBackward;
|
||||
for (UInt_t i=1; i<fRunInfo->GetRunNameSize(); i++) {
|
||||
// get run to be added to the main one
|
||||
addRunData = fRawData->GetRunData(*(fRunInfo->GetRunName(i)));
|
||||
@@ -644,6 +741,22 @@ Bool_t PRunAsymmetry::PrepareData()
|
||||
return false;
|
||||
}
|
||||
|
||||
// dead time correction handling
|
||||
addForward.clear();
|
||||
addForward.resize(forwardHistoNo.size());
|
||||
for (UInt_t j=0; j<forwardHistoNo.size(); j++) {
|
||||
addForward[j].resize(addRunData->GetDataBin(forwardHistoNo[j])->size());
|
||||
addForward[j] = *addRunData->GetDataBin(forwardHistoNo[j]);
|
||||
}
|
||||
DeadTimeCorrection(addForward, forwardHistoNo);
|
||||
addBackward.clear();
|
||||
addBackward.resize(backwardHistoNo.size());
|
||||
for (UInt_t j=0; j<backwardHistoNo.size(); j++) {
|
||||
addBackward[j].resize(addRunData->GetDataBin(backwardHistoNo[j])->size());
|
||||
addBackward[j] = *addRunData->GetDataBin(backwardHistoNo[j]);
|
||||
}
|
||||
DeadTimeCorrection(addBackward, backwardHistoNo);
|
||||
|
||||
// add forward run
|
||||
UInt_t addRunSize;
|
||||
for (UInt_t k=0; k<forwardHistoNo.size(); k++) { // fill each group
|
||||
@@ -652,7 +765,7 @@ Bool_t PRunAsymmetry::PrepareData()
|
||||
// make sure that the index stays in the proper range
|
||||
if ((static_cast<Int_t>(j)+static_cast<Int_t>(fAddT0s[i-1][2*k])-static_cast<Int_t>(fT0s[2*k]) >= 0) &&
|
||||
(j+static_cast<Int_t>(fAddT0s[i-1][2*k])-static_cast<Int_t>(fT0s[2*k]) < addRunSize)) {
|
||||
forward[k][j] += addRunData->GetDataBin(forwardHistoNo[k])->at(j+static_cast<Int_t>(fAddT0s[i-1][2*k])-static_cast<Int_t>(fT0s[2*k]));
|
||||
forward[k][j] += addForward[k][j+static_cast<Int_t>(fAddT0s[i-1][2*k])-static_cast<Int_t>(fT0s[2*k])];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -664,7 +777,7 @@ Bool_t PRunAsymmetry::PrepareData()
|
||||
// make sure that the index stays in the proper range
|
||||
if ((static_cast<Int_t>(j)+static_cast<Int_t>(fAddT0s[i-1][2*k+1])-static_cast<Int_t>(fT0s[2*k+1]) >= 0) &&
|
||||
(j+static_cast<Int_t>(fAddT0s[i-1][2*k+1])-static_cast<Int_t>(fT0s[2*k+1]) < addRunSize)) {
|
||||
backward[k][j] += addRunData->GetDataBin(backwardHistoNo[k])->at(j+static_cast<Int_t>(fAddT0s[i-1][2*k+1])-static_cast<Int_t>(fT0s[2*k+1]));
|
||||
backward[k][j] += addBackward[k][j+static_cast<Int_t>(fAddT0s[i-1][2*k+1])-static_cast<Int_t>(fT0s[2*k+1])];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -942,15 +1055,24 @@ Bool_t PRunAsymmetry::SubtractEstimatedBkg()
|
||||
// PrepareFitData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Take the pre-processed data (i.e. grouping and addrun are preformed) and form the asymmetry for fitting.
|
||||
* Before forming the asymmetry, the following checks will be performed:
|
||||
* -# check if data range is given, if not try to estimate one.
|
||||
* -# check that if a data range is present, that it makes any sense.
|
||||
* -# check that 'first good bin'-'t0' is the same for forward and backward histogram. If not adjust it.
|
||||
* -# pack data (rebin).
|
||||
* -# if packed forward size != backward size, truncate the longer one such that an asymmetry can be formed.
|
||||
* -# calculate the asymmetry: \f$ A_i = (f_i^c-b_i^c)/(f_i^c+b_i^c) \f$
|
||||
* -# calculate the asymmetry errors: \f$ \delta A_i = 2 \sqrt{(b_i^c)^2 (\delta f_i^c)^2 + (\delta b_i^c)^2 (f_i^c)^2}/(f_i^c+b_i^c)^2\f$
|
||||
* \brief Processes pre-grouped data and calculates asymmetry for fitting.
|
||||
*
|
||||
* Takes forward/backward histograms (after grouping and addrun operations) and performs
|
||||
* final processing steps for fitting:
|
||||
*
|
||||
* 1. Validates data range, estimates if not specified
|
||||
* 2. Checks data range consistency and validity
|
||||
* 3. Aligns forward/backward histograms (ensures 'first good bin - t0' is identical)
|
||||
* 4. Applies bin packing (rebinning) if requested
|
||||
* 5. Truncates longer histogram if packed sizes differ
|
||||
* 6. Calculates asymmetry: \f$ A_i = (f_i^{\rm c}-b_i^{\rm c})/(f_i^{\rm c}+b_i^{\rm c}) \f$
|
||||
* 7. Propagates errors: \f$ \delta A_i = \frac{2}{(f_i^{\rm c}+b_i^{\rm c})^2}\sqrt{(b_i^{\rm c})^2 (\delta f_i^{\rm c})^2 + (f_i^{\rm c})^2 (\delta b_i^{\rm c})^2} \f$
|
||||
*
|
||||
* Bin packing averages multiple bins to improve statistics:
|
||||
* - Packed value normalized to per-bin counts (value/packing)
|
||||
* - Error propagation: \f$ \sigma_{\rm packed} = \sqrt{\sum \sigma_i^2}/N_{\rm pack} \f$
|
||||
*
|
||||
* \return True on success, false if data preparation fails
|
||||
*/
|
||||
Bool_t PRunAsymmetry::PrepareFitData()
|
||||
{
|
||||
@@ -1056,20 +1178,25 @@ Bool_t PRunAsymmetry::PrepareFitData()
|
||||
// PrepareViewData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Take the pre-processed data (i.e. grouping and addrun are preformed) and form the asymmetry for view representation.
|
||||
* Before forming the asymmetry, the following checks will be performed:
|
||||
* -# check if view packing is whished.
|
||||
* -# check if data range is given, if not try to estimate one.
|
||||
* -# check that data range is present, that it makes any sense.
|
||||
* -# check that 'first good bin'-'t0' is the same for forward and backward histogram. If not adjust it.
|
||||
* -# pack data (rebin).
|
||||
* -# if packed forward size != backward size, truncate the longer one such that an asymmetry can be formed.
|
||||
* -# calculate the asymmetry: \f$ A_i = (\alpha f_i^c-b_i^c)/(\alpha \beta f_i^c+b_i^c) \f$
|
||||
* -# calculate the asymmetry errors: \f$ \delta A_i = 2 \sqrt{(b_i^c)^2 (\delta f_i^c)^2 + (\delta b_i^c)^2 (f_i^c)^2}/(f_i^c+b_i^c)^2\f$
|
||||
* -# calculate the theory vector.
|
||||
* \brief Prepares asymmetry data for plotting and visualization.
|
||||
*
|
||||
* \param runData raw run data needed to perform some crosschecks
|
||||
* \param histoNo histogram number (within a run). histoNo[0]: forward histogram number, histNo[1]: backward histogram number
|
||||
* Processes pre-grouped data for display in plots, with special handling for view packing
|
||||
* and α/β corrections. Similar to PrepareFitData but includes theory calculation and
|
||||
* supports separate view packing settings.
|
||||
*
|
||||
* Processing steps:
|
||||
* 1. Checks for view-specific packing (overrides fit packing for display)
|
||||
* 2. Validates and estimates data range if needed
|
||||
* 3. Aligns forward/backward histogram start bins relative to t0
|
||||
* 4. Applies bin packing for improved visualization
|
||||
* 5. Ensures equal bin counts between forward/backward after packing
|
||||
* 6. Calculates asymmetry with α/β corrections: \f$ A_i = (\alpha f_i^{\rm c} - b_i^{\rm c})/(\alpha \beta f_i^{\rm c} + b_i^{\rm c}) \f$
|
||||
* 7. Propagates errors: \f$ \delta A_i = \frac{2}{(f_i^{\rm c}+b_i^{\rm c})^2}\sqrt{(b_i^{\rm c})^2 (\delta f_i^{\rm c})^2 + (f_i^{\rm c})^2 (\delta b_i^{\rm c})^2} \f$
|
||||
* 8. Calculates theory curve for overlay
|
||||
*
|
||||
* \param runData Pointer to raw run data for validation and cross-checks
|
||||
* \param histoNo Array of histogram indices: [0]=forward, [1]=backward
|
||||
* \return True on success, false on error
|
||||
*/
|
||||
Bool_t PRunAsymmetry::PrepareViewData(PRawRunData* runData, UInt_t histoNo[2])
|
||||
{
|
||||
@@ -1341,19 +1468,27 @@ Bool_t PRunAsymmetry::PrepareViewData(PRawRunData* runData, UInt_t histoNo[2])
|
||||
// PrepareRRFViewData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p> Prepares the RRF data set for visual representation. This is done the following way:
|
||||
* -# make all necessary checks
|
||||
* -# build the asymmetry, \f$ A(t) \f$, WITHOUT packing.
|
||||
* -# \f$ A_R(t) = A(t) \cdot 2 \cos(\omega_R t + \phi_R) \f$
|
||||
* -# do the packing of \f$ A_R(t) \f$
|
||||
* -# calculate theory, \f$ T(t) \f$, as close as possible to the time resolution [compatible with the RRF frequency]
|
||||
* -# \f$ T_R(t) = T(t) \cdot 2 \cos(\omega_R t + \phi_R) \f$
|
||||
* -# do the packing of \f$ T_R(t) \f$
|
||||
* -# calculate the Kaiser FIR filter coefficients
|
||||
* -# filter \f$ T_R(t) \f$.
|
||||
* \brief Prepares rotating reference frame (RRF) data for visualization.
|
||||
*
|
||||
* \param runData raw run data needed to perform some crosschecks
|
||||
* \param histoNo array of the histo numbers form which to build the asymmetry
|
||||
* Transforms asymmetry data into a rotating reference frame for analyzing high-frequency
|
||||
* oscillations. The RRF technique mixes the data with a reference frequency to shift
|
||||
* oscillations down to lower frequencies, making them easier to visualize and analyze.
|
||||
*
|
||||
* Processing sequence:
|
||||
* 1. Validates data ranges and histogram alignment
|
||||
* 2. Builds asymmetry \f$ A(t) \f$ without packing
|
||||
* 3. Applies RRF transformation: \f$ A_R(t) = A(t) \cdot 2\cos(\omega_R t + \phi_R) \f$
|
||||
* 4. Packs the RRF asymmetry data
|
||||
* 5. Calculates theory \f$ T(t) \f$ at high time resolution
|
||||
* 6. Transforms theory to RRF: \f$ T_R(t) = T(t) \cdot 2\cos(\omega_R t + \phi_R) \f$
|
||||
* 7. Packs the RRF theory curve
|
||||
* 8. Applies Kaiser FIR filter to smooth the theory curve
|
||||
*
|
||||
* The RRF frequency (\f$ \omega_R \f$) and phase (\f$ \phi_R \f$) are specified in the PLOT block.
|
||||
*
|
||||
* \param runData Pointer to raw run data for validation
|
||||
* \param histoNo Array of histogram indices: [0]=forward, [1]=backward
|
||||
* \return True on success, false on error
|
||||
*/
|
||||
Bool_t PRunAsymmetry::PrepareRRFViewData(PRawRunData* runData, UInt_t histoNo[2])
|
||||
{
|
||||
@@ -1675,22 +1810,32 @@ Bool_t PRunAsymmetry::PrepareRRFViewData(PRawRunData* runData, UInt_t histoNo[2]
|
||||
// GetProperT0 (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the proper t0 for the single histogram run.
|
||||
* -# the t0 vector size = number of detectors (grouping) for forward + backward.
|
||||
* -# initialize t0's with -1
|
||||
* -# fill t0's from RUN block
|
||||
* -# if t0's are missing (i.e. t0 == -1), try to fill from the GLOBAL block.
|
||||
* -# if t0's are missing, try t0's from the data file
|
||||
* -# if t0's are missing, try to estimate them
|
||||
* \brief Determines and validates t0 values for all forward and backward histograms.
|
||||
*
|
||||
* \param runData pointer to the current RUN block entry from the msr-file
|
||||
* \param globalBlock pointer to the GLOBLA block entry from the msr-file
|
||||
* \param forwardHistoNo histogram number vector of forward; forwardHistoNo = msr-file forward + redGreen_offset - 1
|
||||
* \param backwardHistoNo histogram number vector of backwardward; backwardHistoNo = msr-file backward + redGreen_offset - 1
|
||||
* Time zero (t0) marks the arrival time of muons in the sample and is critical for
|
||||
* proper time alignment. This method attempts to find t0 values from multiple sources
|
||||
* with a well-defined fallback hierarchy:
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if everthing went smooth
|
||||
* - false, otherwise.
|
||||
* Priority order:
|
||||
* 1. Individual RUN block t0 values (highest priority, user-specified)
|
||||
* 2. GLOBAL block t0 values (shared defaults for all runs)
|
||||
* 3. Data file t0 values (from detector electronics or auto-detection)
|
||||
* 4. Estimated t0 values (last resort, may be unreliable for some facilities)
|
||||
*
|
||||
* The t0 vector is organized as [forward_0, backward_0, forward_1, backward_1, ...],
|
||||
* accommodating different numbers of forward/backward histograms in grouped data.
|
||||
*
|
||||
* Also handles addT0 values for runs being added together, ensuring proper time alignment
|
||||
* when combining multiple datasets.
|
||||
*
|
||||
* \param runData Pointer to raw run data containing file-based t0 information
|
||||
* \param globalBlock Pointer to GLOBAL block with default t0 settings
|
||||
* \param forwardHistoNo Vector of forward histogram indices (after red/green offset adjustment)
|
||||
* \param backwardHistoNo Vector of backward histogram indices (after red/green offset adjustment)
|
||||
*
|
||||
* \return True on success, false if critical t0 values cannot be determined
|
||||
*
|
||||
* \warning Estimated t0 values may be unreliable for certain facilities (e.g., LEM)
|
||||
*/
|
||||
Bool_t PRunAsymmetry::GetProperT0(PRawRunData* runData, PMsrGlobalBlock *globalBlock, PUIntVector &forwardHistoNo, PUIntVector &backwardHistoNo)
|
||||
{
|
||||
@@ -1855,17 +2000,30 @@ Bool_t PRunAsymmetry::GetProperT0(PRawRunData* runData, PMsrGlobalBlock *globalB
|
||||
// GetProperDataRange (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the proper data range, i.e. first/last good bin (fgb/lgb).
|
||||
* -# get fgb/lgb from the RUN block
|
||||
* -# if fgb/lgb still undefined, try to get it from the GLOBAL block
|
||||
* -# if fgb/lgb still undefined, try to estimate them.
|
||||
* \brief Determines the valid data range (first/last good bins) for analysis.
|
||||
*
|
||||
* \param runData raw run data needed to perform some crosschecks
|
||||
* \param histoNo histogram number (within a run). histoNo[0]: forward histogram number, histNo[1]: backward histogram number
|
||||
* The data range defines which portion of the histograms contains usable data,
|
||||
* excluding initial and final bins that may be noisy or affected by detector artifacts.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if everthing went smooth
|
||||
* - false, otherwise.
|
||||
* Determination hierarchy:
|
||||
* 1. RUN block data range settings (highest priority, run-specific)
|
||||
* 2. GLOBAL block data range (shared defaults)
|
||||
* 3. Estimated range (last resort: start = t0 + 10ns, end = histogram length)
|
||||
*
|
||||
* Performs validation checks:
|
||||
* - Ensures start < end (swaps if needed)
|
||||
* - Verifies bins are within histogram bounds [0, histogram size]
|
||||
* - Validates t0 is within valid range
|
||||
* - Clips end bin if it exceeds histogram length
|
||||
*
|
||||
* The good bins are stored in fGoodBins as [forward_start, forward_end, backward_start, backward_end].
|
||||
*
|
||||
* \param runData Pointer to raw run data for histogram size validation
|
||||
* \param histoNo Array of histogram indices: [0]=forward, [1]=backward
|
||||
*
|
||||
* \return True on success, false if data range is invalid or out of bounds
|
||||
*
|
||||
* \warning Estimated data ranges may not be appropriate for all experiments
|
||||
*/
|
||||
Bool_t PRunAsymmetry::GetProperDataRange(PRawRunData* runData, UInt_t histoNo[2])
|
||||
{
|
||||
@@ -2000,16 +2158,26 @@ Bool_t PRunAsymmetry::GetProperDataRange(PRawRunData* runData, UInt_t histoNo[2]
|
||||
// GetProperFitRange (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the proper fit range. There are two possible fit range commands:
|
||||
* fit <start> <end> given in (usec), or
|
||||
* fit fgb+offset_0 lgb-offset_1 given in (bins), therefore it works the following way:
|
||||
* -# get fit range assuming given in time from RUN block
|
||||
* -# if fit range in RUN block is given in bins, replace start/end
|
||||
* -# if fit range is NOT given yet, try fit range assuming given in time from GLOBAL block
|
||||
* -# if fit range in GLOBAL block is given in bins, replace start/end
|
||||
* -# if still no fit range is given, use fgb/lgb.
|
||||
* \brief Determines the fit range for χ² minimization.
|
||||
*
|
||||
* \param globalBlock pointer to the GLOBAL block information form the msr-file.
|
||||
* The fit range defines the time window used for parameter fitting. It can be specified
|
||||
* in two formats:
|
||||
* - Time-based: "fit start end" in microseconds (e.g., "fit 0.1 10.0")
|
||||
* - Bin-based: "fit fgb+offset lgb-offset" using good bin boundaries (e.g., "fit fgb+5 lgb-10")
|
||||
*
|
||||
* Determination sequence:
|
||||
* 1. Checks RUN block for time-based fit range
|
||||
* 2. If RUN block specifies bin-based range, converts to time using fgb/lgb offsets
|
||||
* 3. Falls back to GLOBAL block fit range (time or bin-based) if RUN block is empty
|
||||
* 4. Uses full data range (fgb to lgb) if no fit range is specified
|
||||
*
|
||||
* Bin-based format allows fine-tuning relative to good bin boundaries:
|
||||
* - fgb+n: Start n bins after first good bin
|
||||
* - lgb-n: End n bins before last good bin
|
||||
*
|
||||
* The resulting fit range is stored as time values in fFitStartTime and fFitEndTime.
|
||||
*
|
||||
* \param globalBlock Pointer to GLOBAL block containing default fit range settings
|
||||
*/
|
||||
void PRunAsymmetry::GetProperFitRange(PMsrGlobalBlock *globalBlock)
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2018-2025 by Zaher Salman *
|
||||
* Copyright (C) 2018-2026 by Zaher Salman *
|
||||
* zaher.salman@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -51,7 +51,11 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Default constructor that initializes all member variables.
|
||||
*
|
||||
* Sets all counters and indices to default/invalid values. This constructor
|
||||
* creates an invalid instance that requires proper initialization via the
|
||||
* main constructor.
|
||||
*/
|
||||
PRunAsymmetryBNMR::PRunAsymmetryBNMR() : PRunBase()
|
||||
{
|
||||
@@ -72,12 +76,28 @@ PRunAsymmetryBNMR::PRunAsymmetryBNMR() : PRunBase()
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Main constructor that initializes β-NMR asymmetry fitting.
|
||||
*
|
||||
* \param msrInfo pointer to the msr-file handler
|
||||
* \param rawData raw run data
|
||||
* \param runNo number of the run within the msr-file
|
||||
* \param tag tag showing what shall be done: kFit == fitting, kView == viewing
|
||||
* Performs comprehensive initialization:
|
||||
* 1. Validates packing parameter from RUN or GLOBAL block
|
||||
* 2. Determines α/β parameter configuration (tags 1-6)
|
||||
* 3. Validates α and β parameter numbers
|
||||
* 4. Sets fAlphaBetaTag based on whether α/β are fixed to 1, free, or auto-estimated
|
||||
* 5. Calls PrepareData() to load and process histogram data
|
||||
*
|
||||
* The α/β tag determines the asymmetry calculation method:
|
||||
* - Tag 1: Both α=1 and β=1 (simplest case)
|
||||
* - Tag 2: α free, β=1 (one asymmetry parameter)
|
||||
* - Tag 3: α=1, β free (alternative single parameter)
|
||||
* - Tag 4: Both α and β free (most general)
|
||||
* - Tag 5: α auto-estimated, β=1 (automatic calibration)
|
||||
* - Tag 6: α auto-estimated, β free
|
||||
*
|
||||
* \param msrInfo Pointer to MSR file handler
|
||||
* \param rawData Pointer to raw run data handler
|
||||
* \param runNo Run number within the MSR file
|
||||
* \param tag Operation mode (kFit or kView)
|
||||
* \param theoAsData If true, calculate theory only at data points
|
||||
*/
|
||||
PRunAsymmetryBNMR::PRunAsymmetryBNMR(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t runNo, EPMusrHandleTag tag, Bool_t theoAsData) :
|
||||
PRunBase(msrInfo, rawData, runNo, tag), fTheoAsData(theoAsData)
|
||||
@@ -166,7 +186,10 @@ PRunAsymmetryBNMR::PRunAsymmetryBNMR(PMsrHandler *msrInfo, PRunDataHandler *rawD
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor.
|
||||
* \brief Destructor that cleans up helicity histogram data.
|
||||
*
|
||||
* Clears all eight histogram vectors (forward/backward × positive/negative helicity
|
||||
* × data/errors) to free memory.
|
||||
*/
|
||||
PRunAsymmetryBNMR::~PRunAsymmetryBNMR()
|
||||
{
|
||||
@@ -185,12 +208,20 @@ PRunAsymmetryBNMR::~PRunAsymmetryBNMR()
|
||||
// CalcChiSquare (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate chi-square.
|
||||
* \brief Calculates chi-square for β-NMR asymmetry fit.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value
|
||||
* Computes χ² by comparing the asymmetry function with the theory:
|
||||
* χ² = Σ[(A_data - A_theory)²/σ²]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* The asymmetry depends on fAlphaBetaTag:
|
||||
* - Tag 1 (α=β=1): A = (F+ - B+) / (F+ + B+)
|
||||
* - Tag 2-4: Various combinations with α and/or β corrections
|
||||
* - Tag 5-6: Auto-estimated α
|
||||
*
|
||||
* Supports OpenMP parallelization for faster calculation.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT minimizer
|
||||
* \return Chi-square value
|
||||
*/
|
||||
Double_t PRunAsymmetryBNMR::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -303,12 +334,13 @@ Double_t PRunAsymmetryBNMR::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
// CalcChiSquareExpected (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate expected chi-square. Currently not implemented since not clear what to be done.
|
||||
* \brief Calculates expected chi-square (not yet implemented).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value == 0.0
|
||||
* This method is intended for statistical analysis of fit quality, but
|
||||
* implementation is pending due to complexity of β-NMR asymmetry calculation.
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* \param par Parameter vector from MINUIT (unused)
|
||||
* \return Always returns 0.0 (placeholder)
|
||||
*/
|
||||
Double_t PRunAsymmetryBNMR::CalcChiSquareExpected(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -319,9 +351,13 @@ Double_t PRunAsymmetryBNMR::CalcChiSquareExpected(const std::vector<Double_t>& p
|
||||
// CalcMaxLikelihood (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>NOT IMPLEMENTED!!
|
||||
* \brief Calculates maximum likelihood estimator (not yet implemented).
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* Maximum likelihood fitting for β-NMR asymmetry is not yet implemented.
|
||||
* Prints warning message when called.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT (unused)
|
||||
* \return Always returns 1.0 (placeholder)
|
||||
*/
|
||||
Double_t PRunAsymmetryBNMR::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -334,9 +370,11 @@ Double_t PRunAsymmetryBNMR::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
// GetNoOfFitBins (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the number of fitted bins for the current fit range.
|
||||
* \brief Returns the number of bins used in the fit.
|
||||
*
|
||||
* <b>return:</b> number of fitted bins.
|
||||
* Calls CalcNoOfFitBins() to update fNoOfFitBins before returning the value.
|
||||
*
|
||||
* \return Number of bins included in the fit range
|
||||
*/
|
||||
UInt_t PRunAsymmetryBNMR::GetNoOfFitBins()
|
||||
{
|
||||
@@ -349,15 +387,22 @@ UInt_t PRunAsymmetryBNMR::GetNoOfFitBins()
|
||||
// SetFitRangeBin (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Allows to change the fit range on the fly. Used in the COMMAND block.
|
||||
* The syntax of the string is: FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]].
|
||||
* If only one pair of fgb/lgb is given, it is used for all runs in the RUN block section.
|
||||
* If multiple fgb/lgb's are given, the number N has to be the number of RUN blocks in
|
||||
* the msr-file.
|
||||
* \brief Dynamically changes the fit range (used in COMMAND block).
|
||||
*
|
||||
* <p>nXY are offsets which can be used to shift, limit the fit range.
|
||||
* Parses a fit range string to update fit boundaries. The string format is:
|
||||
* - Single range: FIT_RANGE fgb[+n0] lgb[-n1]
|
||||
* - Multiple runs: FIT_RANGE fgb[+n00] lgb[-n01] fgb[+n10] lgb[-n11] ...
|
||||
*
|
||||
* \param fitRange string containing the necessary information.
|
||||
* Where:
|
||||
* - fgb = first good bin
|
||||
* - lgb = last good bin
|
||||
* - +n = positive offset to shift fgb forward
|
||||
* - -n = negative offset to shift lgb backward
|
||||
*
|
||||
* If one pair is given, it applies to all runs. If multiple pairs are given,
|
||||
* the number must match the number of RUN blocks.
|
||||
*
|
||||
* \param fitRange String containing fit range specification
|
||||
*/
|
||||
void PRunAsymmetryBNMR::SetFitRangeBin(const TString fitRange)
|
||||
{
|
||||
@@ -439,7 +484,11 @@ void PRunAsymmetryBNMR::SetFitRangeBin(const TString fitRange)
|
||||
// CalcNoOfFitBins (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the number of fitted bins for the current fit range.
|
||||
* \brief Calculates the number of bins in the fit range.
|
||||
*
|
||||
* Converts fit time range (fFitStartTime, fFitEndTime) to bin indices
|
||||
* (fStartTimeBin, fEndTimeBin) and calculates fNoOfFitBins. Performs
|
||||
* boundary checking to ensure indices stay within valid data range.
|
||||
*/
|
||||
void PRunAsymmetryBNMR::CalcNoOfFitBins()
|
||||
{
|
||||
@@ -461,7 +510,19 @@ void PRunAsymmetryBNMR::CalcNoOfFitBins()
|
||||
// CalcTheory (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate theory for a given set of fit-parameters.
|
||||
* \brief Calculates theoretical β-NMR asymmetry values.
|
||||
*
|
||||
* Computes theory points for all data bins using the current parameters.
|
||||
* The calculation method depends on fAlphaBetaTag:
|
||||
*
|
||||
* - Tag 1 (α=β=1): A = f(t)
|
||||
* - Tag 2 (α≠1, β=1): A = [f(α+1)-(α-1)]/[(α+1)-f(α-1)] - [-f(α+1)-(α-1)]/[(α+1)+f(α-1)]
|
||||
* - Tag 3 (α=1, β≠1): A = f(β+1)/[2-f(β-1)] - f(β+1)/[2+f(β-1)]
|
||||
* - Tag 4 (α≠1, β≠1): Combined formula with both α and β corrections
|
||||
* - Tag 5 (α estimated, β=1): Uses auto-estimated α
|
||||
* - Tag 6 (α estimated, β≠1): Uses auto-estimated α with β correction
|
||||
*
|
||||
* where f(t) is the theory function from the FIT block.
|
||||
*/
|
||||
void PRunAsymmetryBNMR::CalcTheory()
|
||||
{
|
||||
@@ -567,23 +628,25 @@ void PRunAsymmetryBNMR::CalcTheory()
|
||||
// PrepareData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Prepare data for fitting or viewing. What is already processed at this stage:
|
||||
* - get all needed forward/backward histograms
|
||||
* - get time resolution
|
||||
* - get start/stop fit time
|
||||
* - get t0's and perform necessary cross checks (e.g. if t0 of msr-file (if present) are consistent with t0 of the data files, etc.)
|
||||
* - add runs (if addruns are present)
|
||||
* - group histograms (if grouping is present)
|
||||
* - subtract background
|
||||
* \brief Prepares β-NMR asymmetry data for fitting or viewing.
|
||||
*
|
||||
* Error propagation for \f$ A_i = (f_i^{\rm c}-b_i^{\rm c})/(f_i^{\rm c}+b_i^{\rm c})\f$:
|
||||
* \f[ \Delta A_i = \pm\frac{2}{(f_i^{\rm c}+b_i^{\rm c})^2}\left[
|
||||
* (b_i^{\rm c})^2 (\Delta f_i^{\rm c})^2 +
|
||||
* (\Delta b_i^{\rm c})^2 (f_i^{\rm c})^2\right]^{1/2}\f]
|
||||
* Main data preparation routine that performs the following steps:
|
||||
* 1. Retrieves forward/backward histograms for both helicities
|
||||
* 2. Gets time resolution from data file
|
||||
* 3. Validates t0 values (cross-checks MSR file vs. data file)
|
||||
* 4. Adds runs if addruns are specified
|
||||
* 5. Groups histograms if grouping is specified
|
||||
* 6. Subtracts background (fixed or estimated)
|
||||
* 7. Applies bin packing if specified
|
||||
* 8. Calculates β-NMR asymmetry with proper error propagation
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if everthing went smooth
|
||||
* - false, otherwise.
|
||||
* The asymmetry calculation handles four histograms per helicity:
|
||||
* - Forward+, Backward+, Forward-, Backward-
|
||||
*
|
||||
* Error propagation for asymmetry A = (F-B)/(F+B):
|
||||
* \f[ \Delta A = \pm\frac{2}{(F+B)^2}\sqrt{B^2(\Delta F)^2 + F^2(\Delta B)^2} \f]
|
||||
*
|
||||
* \return True if successful, false on error
|
||||
*/
|
||||
Bool_t PRunAsymmetryBNMR::PrepareData()
|
||||
{
|
||||
@@ -1826,16 +1889,20 @@ Bool_t PRunAsymmetryBNMR::GetProperDataRange(PRawRunData* runData, UInt_t histoN
|
||||
// GetProperFitRange (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the proper fit range. There are two possible fit range commands:
|
||||
* fit <start> <end> given in (usec), or
|
||||
* fit fgb+offset_0 lgb-offset_1 given in (bins), therefore it works the following way:
|
||||
* -# get fit range assuming given in time from RUN block
|
||||
* -# if fit range in RUN block is given in bins, replace start/end
|
||||
* -# if fit range is NOT given yet, try fit range assuming given in time from GLOBAL block
|
||||
* -# if fit range in GLOBAL block is given in bins, replace start/end
|
||||
* -# if still no fit range is given, use fgb/lgb.
|
||||
* \brief Determines the proper fit range for the run.
|
||||
*
|
||||
* \param globalBlock pointer to the GLOBAL block information form the msr-file.
|
||||
* Fit ranges can be specified in two ways:
|
||||
* - Time format: fit <start> <end> in microseconds
|
||||
* - Bin format: fit fgb+offset_0 lgb-offset_1 in bins
|
||||
*
|
||||
* Resolution order:
|
||||
* 1. Check RUN block for fit range (time or bins)
|
||||
* 2. If not found, check GLOBAL block for fit range
|
||||
* 3. If still not found, default to fgb/lgb (first/last good bins)
|
||||
*
|
||||
* For bin format, converts to time using: time = (bin - t0) × time_resolution
|
||||
*
|
||||
* \param globalBlock Pointer to GLOBAL block from MSR file
|
||||
*/
|
||||
void PRunAsymmetryBNMR::GetProperFitRange(PMsrGlobalBlock *globalBlock)
|
||||
{
|
||||
@@ -1875,9 +1942,17 @@ void PRunAsymmetryBNMR::GetProperFitRange(PMsrGlobalBlock *globalBlock)
|
||||
// EstimateAlpha (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get an estimate for alpha from the forward and backward histograms
|
||||
* \brief Estimates the α parameter from histogram data.
|
||||
*
|
||||
* \param globalBlock pointer to the GLOBAL block information form the msr-file.
|
||||
* Calculates an automatic α value by comparing integrated counts in forward
|
||||
* and backward histograms for both helicities. The estimate uses:
|
||||
*
|
||||
* α = √[(F+×B+) / (F-×B-)]
|
||||
*
|
||||
* where F+, B+, F-, B- are the total counts in the respective histograms.
|
||||
* This provides a data-driven calibration when α is not explicitly specified.
|
||||
*
|
||||
* \return Estimated α value (defaults to 1.0 if calculation fails)
|
||||
*/
|
||||
Double_t PRunAsymmetryBNMR::EstimateAlpha()
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -51,7 +51,11 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Default constructor that initializes all member variables.
|
||||
*
|
||||
* Sets all counters and indices to default/invalid values. This constructor
|
||||
* creates an invalid instance that requires proper initialization via the
|
||||
* main constructor.
|
||||
*/
|
||||
PRunAsymmetryRRF::PRunAsymmetryRRF() : PRunBase()
|
||||
{
|
||||
@@ -69,12 +73,30 @@ PRunAsymmetryRRF::PRunAsymmetryRRF() : PRunBase()
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Main constructor that initializes RRF asymmetry fitting.
|
||||
*
|
||||
* \param msrInfo pointer to the msr-file handler
|
||||
* \param rawData raw run data
|
||||
* \param runNo number of the run within the msr-file
|
||||
* \param tag tag showing what shall be done: kFit == fitting, kView == viewing
|
||||
* Performs comprehensive initialization for rotating reference frame analysis:
|
||||
* 1. Validates RRF packing parameter from GLOBAL block (required for RRF)
|
||||
* 2. Validates α parameter (required for asymmetry)
|
||||
* 3. Validates β parameter (optional, defaults to 1)
|
||||
* 4. Determines α/β configuration tag (1-4)
|
||||
* 5. Calls PrepareData() to load and process histogram data with RRF transformation
|
||||
*
|
||||
* The α/β tag determines the asymmetry calculation method:
|
||||
* - Tag 1: α=1, β=1 (no corrections)
|
||||
* - Tag 2: α≠1, β=1 (forward/backward correction)
|
||||
* - Tag 3: α=1, β≠1 (alternative correction)
|
||||
* - Tag 4: α≠1, β≠1 (both corrections)
|
||||
*
|
||||
* RRF packing must be specified in the GLOBAL block (e.g., "rrf_packing 50").
|
||||
* This parameter controls the rebinning after RRF transformation and is essential
|
||||
* for proper signal extraction in the rotating frame.
|
||||
*
|
||||
* \param msrInfo Pointer to MSR file handler
|
||||
* \param rawData Pointer to raw run data handler
|
||||
* \param runNo Run number within the MSR file
|
||||
* \param tag Operation mode (kFit or kView)
|
||||
* \param theoAsData If true, calculate theory only at data points
|
||||
*/
|
||||
PRunAsymmetryRRF::PRunAsymmetryRRF(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t runNo, EPMusrHandleTag tag, Bool_t theoAsData) :
|
||||
PRunBase(msrInfo, rawData, runNo, tag), fTheoAsData(theoAsData)
|
||||
@@ -153,7 +175,10 @@ PRunAsymmetryRRF::PRunAsymmetryRRF(PMsrHandler *msrInfo, PRunDataHandler *rawDat
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor.
|
||||
* \brief Destructor that cleans up histogram data.
|
||||
*
|
||||
* Clears all four histogram vectors (forward/backward × data/errors)
|
||||
* to free memory.
|
||||
*/
|
||||
PRunAsymmetryRRF::~PRunAsymmetryRRF()
|
||||
{
|
||||
@@ -167,12 +192,24 @@ PRunAsymmetryRRF::~PRunAsymmetryRRF()
|
||||
// CalcChiSquare (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate chi-square.
|
||||
* \brief Calculates chi-square for RRF asymmetry fit.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value
|
||||
* Computes χ² by comparing the measured RRF-transformed asymmetry with theory:
|
||||
* χ² = Σ[(A_RRF,data - A_RRF,theory)²/σ²]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* The RRF asymmetry has already been calculated in PrepareData() by applying
|
||||
* the transformation: A_RRF(t) = A(t) · 2cos(ω_RRF·t + φ_RRF)
|
||||
*
|
||||
* The theory function is similarly transformed and includes α/β corrections:
|
||||
* - Tag 1 (α=β=1): A = f(t)
|
||||
* - Tag 2 (α≠1, β=1): A = [f(t)(α+1) - (α-1)] / [(α+1) - f(t)(α-1)]
|
||||
* - Tag 3 (α=1, β≠1): Uses β correction
|
||||
* - Tag 4 (α≠1, β≠1): Uses both α and β corrections
|
||||
*
|
||||
* Supports OpenMP parallelization for faster calculation.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT minimizer
|
||||
* \return Chi-square value
|
||||
*/
|
||||
Double_t PRunAsymmetryRRF::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -269,12 +306,17 @@ Double_t PRunAsymmetryRRF::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
// CalcChiSquareExpected (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate expected chi-square. Currently not implemented since not clear what to be done.
|
||||
* \brief Calculates expected chi-square value.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value == 0.0
|
||||
* This function is currently not implemented for RRF asymmetry fits because the expected
|
||||
* chi-square calculation for RRF-transformed asymmetry data requires a complex statistical
|
||||
* treatment. The RRF transformation introduces correlations between adjacent bins that
|
||||
* complicate the expected value calculation.
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* \param par Parameter vector from MINUIT minimizer
|
||||
* \return Always returns 0.0 (placeholder value)
|
||||
*
|
||||
* \todo Implement proper expected chi-square calculation for RRF asymmetry fits
|
||||
*/
|
||||
Double_t PRunAsymmetryRRF::CalcChiSquareExpected(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -285,9 +327,16 @@ Double_t PRunAsymmetryRRF::CalcChiSquareExpected(const std::vector<Double_t>& pa
|
||||
// CalcMaxLikelihood (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>NOT IMPLEMENTED!!
|
||||
* \brief Calculates maximum likelihood estimator for RRF asymmetry fit.
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* Maximum likelihood estimation provides an alternative to χ² minimization and can be
|
||||
* more appropriate for low-count data. However, the proper likelihood function for
|
||||
* RRF-transformed μSR asymmetry data is complex and not yet implemented.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT minimizer
|
||||
* \return Placeholder value of 1.0
|
||||
*
|
||||
* \todo Implement proper Poisson-based maximum likelihood for RRF asymmetry fits
|
||||
*/
|
||||
Double_t PRunAsymmetryRRF::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -300,9 +349,13 @@ Double_t PRunAsymmetryRRF::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
// GetNoOfFitBins (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the number of fitted bins for the current fit range.
|
||||
* \brief Returns the number of bins included in the RRF fit.
|
||||
*
|
||||
* <b>return:</b> number of fitted bins.
|
||||
* Calculates and returns the number of RRF-transformed data bins that fall within
|
||||
* the current fit range. This value is used for determining degrees of freedom and
|
||||
* is recalculated when the fit range changes (e.g., via COMMAND block).
|
||||
*
|
||||
* \return Number of data bins included in the fit
|
||||
*/
|
||||
UInt_t PRunAsymmetryRRF::GetNoOfFitBins()
|
||||
{
|
||||
@@ -315,15 +368,28 @@ UInt_t PRunAsymmetryRRF::GetNoOfFitBins()
|
||||
// SetFitRangeBin (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Allows to change the fit range on the fly. Used in the COMMAND block.
|
||||
* The syntax of the string is: FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]].
|
||||
* If only one pair of fgb/lgb is given, it is used for all runs in the RUN block section.
|
||||
* If multiple fgb/lgb's are given, the number N has to be the number of RUN blocks in
|
||||
* the msr-file.
|
||||
* \brief Dynamically changes the fit range in bin units for RRF data.
|
||||
*
|
||||
* <p>nXY are offsets which can be used to shift, limit the fit range.
|
||||
* Allows modification of the fit range at runtime, typically called from the COMMAND block.
|
||||
* Supports bin-based fit ranges with optional offsets for fine-tuning.
|
||||
*
|
||||
* \param fitRange string containing the necessary information.
|
||||
* Syntax formats:
|
||||
* - Single range: FIT_RANGE fgb[+n0] lgb[-n1]
|
||||
* - Applied to all RUN blocks
|
||||
* - Multiple ranges: FIT_RANGE fgb[+n00] lgb[-n01] fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]
|
||||
* - One pair per RUN block (N must equal number of RUN blocks)
|
||||
*
|
||||
* Parameters:
|
||||
* - fgb: First good bin (start of fit range)
|
||||
* - lgb: Last good bin (end of fit range)
|
||||
* - +n: Positive offset to shift start forward
|
||||
* - -n: Negative offset to shift end backward
|
||||
*
|
||||
* Example: "FIT_RANGE 10+5 200-10" uses bins [15, 190] for fitting
|
||||
*
|
||||
* Note: The bins refer to the RRF-packed data, not the original histograms.
|
||||
*
|
||||
* \param fitRange String containing fit range specification
|
||||
*/
|
||||
void PRunAsymmetryRRF::SetFitRangeBin(const TString fitRange)
|
||||
{
|
||||
@@ -405,7 +471,16 @@ void PRunAsymmetryRRF::SetFitRangeBin(const TString fitRange)
|
||||
// CalcNoOfFitBins (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the number of fitted bins for the current fit range.
|
||||
* \brief Calculates the number of bins included in the current RRF fit range.
|
||||
*
|
||||
* Determines fStartTimeBin and fEndTimeBin from the fit time range (fFitStartTime, fFitEndTime)
|
||||
* and RRF-transformed data time grid. Ensures that bin indices remain within valid bounds.
|
||||
* The result is stored in fNoOfFitBins.
|
||||
*
|
||||
* This calculation accounts for:
|
||||
* - RRF-packed data time step and start time
|
||||
* - Rounding effects (ceiling for start, floor for end)
|
||||
* - Boundary conditions (clips to [0, RRF data size])
|
||||
*/
|
||||
void PRunAsymmetryRRF::CalcNoOfFitBins()
|
||||
{
|
||||
@@ -427,7 +502,24 @@ void PRunAsymmetryRRF::CalcNoOfFitBins()
|
||||
// CalcTheory (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate theory for a given set of fit-parameters.
|
||||
* \brief Calculates theoretical RRF asymmetry values for the current parameters.
|
||||
*
|
||||
* Computes the expected RRF asymmetry A_RRF(t) for all data points based on the current
|
||||
* parameter values and the user-defined theory function. The calculation depends
|
||||
* on the α/β correction mode:
|
||||
*
|
||||
* - Tag 1 (α=1, β=1): A(t) = f(t)
|
||||
* - Tag 2 (α≠1, β=1): A(t) = [f(t)(α+1) - (α-1)] / [(α+1) - f(t)(α-1)]
|
||||
* - Tag 3 (α=1, β≠1): A(t) = f(t)(β+1) / [2 - f(t)(β-1)]
|
||||
* - Tag 4 (α≠1, β≠1): A(t) = [f(t)(αβ+1) - (α-1)] / [(α+1) - f(t)(αβ-1)]
|
||||
*
|
||||
* where f(t) is the raw theory function from the THEORY block.
|
||||
*
|
||||
* Note: The RRF transformation is applied during data preparation (PrepareViewData),
|
||||
* not here. This function calculates the standard asymmetry theory which is then
|
||||
* transformed to the rotating frame during visualization.
|
||||
*
|
||||
* The calculated values are stored in fData for plotting and comparison with measured RRF data.
|
||||
*/
|
||||
void PRunAsymmetryRRF::CalcTheory()
|
||||
{
|
||||
@@ -511,23 +603,33 @@ void PRunAsymmetryRRF::CalcTheory()
|
||||
// PrepareData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Prepare data for fitting or viewing. What is already processed at this stage:
|
||||
* - get all needed forward/backward histograms
|
||||
* - get time resolution
|
||||
* - get start/stop fit time
|
||||
* - get t0's and perform necessary cross checks (e.g. if t0 of msr-file (if present) are consistent with t0 of the data files, etc.)
|
||||
* - add runs (if addruns are present)
|
||||
* - group histograms (if grouping is present)
|
||||
* - subtract background
|
||||
* \brief Main data preparation routine for RRF asymmetry fitting and viewing.
|
||||
*
|
||||
* Error propagation for \f$ A_i = (f_i^{\rm c}-b_i^{\rm c})/(f_i^{\rm c}+b_i^{\rm c})\f$:
|
||||
* \f[ \Delta A_i = \pm\frac{2}{(f_i^{\rm c}+b_i^{\rm c})^2}\left[
|
||||
* (b_i^{\rm c})^2 (\Delta f_i^{\rm c})^2 +
|
||||
* (\Delta b_i^{\rm c})^2 (f_i^{\rm c})^2\right]^{1/2}\f]
|
||||
* Performs comprehensive data preparation specifically for rotating reference frame analysis:
|
||||
* - Loading forward/backward histograms from data files
|
||||
* - Extracting metadata (field, energy, temperature)
|
||||
* - Determining time resolution from data file
|
||||
* - Validating and retrieving t0 values for all histograms
|
||||
* - Adding multiple runs together (if addruns are specified)
|
||||
* - Grouping multiple histograms (if grouping is specified)
|
||||
* - Subtracting background (fixed or estimated)
|
||||
* - Calculating standard asymmetry and error bars
|
||||
* - NOTE: RRF transformation is NOT applied here (it's done in PrepareFitData/PrepareViewData)
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if everthing went smooth
|
||||
* - false, otherwise.
|
||||
* The standard asymmetry is calculated as:
|
||||
* \f[ A_i = \frac{f_i^{\rm c} - b_i^{\rm c}}{f_i^{\rm c} + b_i^{\rm c}} \f]
|
||||
*
|
||||
* Error propagation (assuming Poisson statistics):
|
||||
* \f[ \Delta A_i = \pm\frac{2}{(f_i^{\rm c}+b_i^{\rm c})^2}\sqrt{
|
||||
* (b_i^{\rm c})^2 (\Delta f_i^{\rm c})^2 +
|
||||
* (f_i^{\rm c})^2 (\Delta b_i^{\rm c})^2} \f]
|
||||
*
|
||||
* where \f$ f_i^{\rm c} \f$ and \f$ b_i^{\rm c} \f$ are background-corrected forward and
|
||||
* backward histograms, respectively.
|
||||
*
|
||||
* The RRF transformation and packing are applied later in PrepareFitData() or PrepareViewData().
|
||||
*
|
||||
* \return True if data preparation succeeds, false on any error
|
||||
*/
|
||||
Bool_t PRunAsymmetryRRF::PrepareData()
|
||||
{
|
||||
@@ -605,16 +707,26 @@ Bool_t PRunAsymmetryRRF::PrepareData()
|
||||
forward[i].resize(runData->GetDataBin(forwardHistoNo[i])->size());
|
||||
forward[i] = *runData->GetDataBin(forwardHistoNo[i]);
|
||||
}
|
||||
// check if a dead time correction has to be done
|
||||
// this will be done automatically in the function itself, which also
|
||||
// checks in the global and run section
|
||||
DeadTimeCorrection(forward, forwardHistoNo);
|
||||
|
||||
backward.resize(backwardHistoNo.size()); // resize to number of groups
|
||||
for (UInt_t i=0; i<backwardHistoNo.size(); i++) {
|
||||
backward[i].resize(runData->GetDataBin(backwardHistoNo[i])->size());
|
||||
backward[i] = *runData->GetDataBin(backwardHistoNo[i]);
|
||||
}
|
||||
// check if a dead time correction has to be done
|
||||
// this will be done automatically in the function itself, which also
|
||||
// checks in the global and run section
|
||||
DeadTimeCorrection(forward, forwardHistoNo);
|
||||
|
||||
// check if addrun's are present, and if yes add data
|
||||
// check if there are runs to be added to the current one
|
||||
if (fRunInfo->GetRunNameSize() > 1) { // runs to be added present
|
||||
PRawRunData *addRunData;
|
||||
std::vector<PDoubleVector> addForward, addBackward;
|
||||
for (UInt_t i=1; i<fRunInfo->GetRunNameSize(); i++) {
|
||||
// get run to be added to the main one
|
||||
addRunData = fRawData->GetRunData(*(fRunInfo->GetRunName(i)));
|
||||
@@ -624,6 +736,22 @@ Bool_t PRunAsymmetryRRF::PrepareData()
|
||||
return false;
|
||||
}
|
||||
|
||||
// dead time correction handling
|
||||
addForward.clear();
|
||||
addForward.resize(forwardHistoNo.size());
|
||||
for (UInt_t j=0; j<forwardHistoNo.size(); j++) {
|
||||
addForward[j].resize(addRunData->GetDataBin(forwardHistoNo[j])->size());
|
||||
addForward[j] = *addRunData->GetDataBin(forwardHistoNo[j]);
|
||||
}
|
||||
DeadTimeCorrection(addForward, forwardHistoNo);
|
||||
addBackward.clear();
|
||||
addBackward.resize(backwardHistoNo.size());
|
||||
for (UInt_t j=0; j<backwardHistoNo.size(); j++) {
|
||||
addBackward[j].resize(addRunData->GetDataBin(backwardHistoNo[j])->size());
|
||||
addBackward[j] = *addRunData->GetDataBin(backwardHistoNo[j]);
|
||||
}
|
||||
DeadTimeCorrection(addBackward, backwardHistoNo);
|
||||
|
||||
// add forward run
|
||||
UInt_t addRunSize;
|
||||
for (UInt_t k=0; k<forwardHistoNo.size(); k++) { // fill each group
|
||||
@@ -631,7 +759,7 @@ Bool_t PRunAsymmetryRRF::PrepareData()
|
||||
for (UInt_t j=0; j<addRunData->GetDataBin(forwardHistoNo[k])->size(); j++) { // loop over the bin indices
|
||||
// make sure that the index stays in the proper range
|
||||
if (((Int_t)j+(Int_t)fAddT0s[i-1][2*k]-(Int_t)fT0s[2*k] >= 0) && (j+(Int_t)fAddT0s[i-1][2*k]-(Int_t)fT0s[2*k] < addRunSize)) {
|
||||
forward[k][j] += addRunData->GetDataBin(forwardHistoNo[k])->at(j+(Int_t)fAddT0s[i-1][2*k]-(Int_t)fT0s[2*k]);
|
||||
forward[k][j] += addForward[k][j+(Int_t)fAddT0s[i-1][2*k]-(Int_t)fT0s[2*k]];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -642,7 +770,7 @@ Bool_t PRunAsymmetryRRF::PrepareData()
|
||||
for (UInt_t j=0; j<addRunData->GetDataBin(backwardHistoNo[k])->size(); j++) { // loop over the bin indices
|
||||
// make sure that the index stays in the proper range
|
||||
if (((Int_t)j+(Int_t)fAddT0s[i-1][2*k+1]-(Int_t)fT0s[2*k+1] >= 0) && (j+(Int_t)fAddT0s[i-1][2*k+1]-(Int_t)fT0s[2*k+1] < addRunSize)) {
|
||||
backward[k][j] += addRunData->GetDataBin(backwardHistoNo[k])->at(j+(Int_t)fAddT0s[i-1][2*k+1]-(Int_t)fT0s[2*k+1]);
|
||||
backward[k][j] += addBackward[k][j+(Int_t)fAddT0s[i-1][2*k+1]-(Int_t)fT0s[2*k+1]];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -899,8 +1027,25 @@ Bool_t PRunAsymmetryRRF::SubtractEstimatedBkg()
|
||||
// PrepareFitData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Take the pre-processed data (i.e. grouping and addrun are preformed, background correction already carried out)
|
||||
* and form the asymmetry for fitting.
|
||||
* \brief Processes pre-grouped data and calculates RRF asymmetry for fitting.
|
||||
*
|
||||
* Takes forward/backward histograms (after grouping, addrun, and background correction) and
|
||||
* performs the RRF transformation for fitting:
|
||||
*
|
||||
* 1. Aligns forward/backward histograms (ensures 'first good bin - t0' is identical)
|
||||
* 2. Calculates standard asymmetry: \f$ A_i = (f_i^{\rm c}-b_i^{\rm c})/(f_i^{\rm c}+b_i^{\rm c}) \f$
|
||||
* 3. Applies RRF transformation: \f$ A_{\rm RRF}(t) = A(t) \cdot 2\cos(\omega_{\rm RRF} t + \phi_{\rm RRF}) \f$
|
||||
* 4. Applies RRF packing (rebinning) to reduce noise after mixing
|
||||
* 5. Propagates errors through both transformations
|
||||
*
|
||||
* Error propagation for asymmetry:
|
||||
* \f[ \delta A_i = \frac{2}{(f_i^{\rm c}+b_i^{\rm c})^2}\sqrt{(b_i^{\rm c})^2 (\delta f_i^{\rm c})^2 + (f_i^{\rm c})^2 (\delta b_i^{\rm c})^2} \f]
|
||||
*
|
||||
* RRF packing averages multiple bins to improve statistics after frequency mixing:
|
||||
* - Packed value: sum of bins / packing factor
|
||||
* - Error: \f$ \sigma_{\rm packed} = \sqrt{\sum \sigma_i^2}/N_{\rm pack} \f$
|
||||
*
|
||||
* \return True on success, false if data preparation fails
|
||||
*/
|
||||
Bool_t PRunAsymmetryRRF::PrepareFitData()
|
||||
{
|
||||
@@ -1015,20 +1160,29 @@ Bool_t PRunAsymmetryRRF::PrepareFitData()
|
||||
// PrepareViewData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Take the pre-processed data (i.e. grouping and addrun are preformed) and form the asymmetry for view representation.
|
||||
* Before forming the asymmetry, the following checks will be performed:
|
||||
* -# check if view packing is whished.
|
||||
* -# check if data range is given, if not try to estimate one.
|
||||
* -# check that data range is present, that it makes any sense.
|
||||
* -# check that 'first good bin'-'t0' is the same for forward and backward histogram. If not adjust it.
|
||||
* -# pack data (rebin).
|
||||
* -# if packed forward size != backward size, truncate the longer one such that an asymmetry can be formed.
|
||||
* -# calculate the asymmetry: \f$ A_i = (\alpha f_i^c-b_i^c)/(\alpha \beta f_i^c+b_i^c) \f$
|
||||
* -# calculate the asymmetry errors: \f$ \delta A_i = 2 \sqrt{(b_i^c)^2 (\delta f_i^c)^2 + (\delta b_i^c)^2 (f_i^c)^2}/(f_i^c+b_i^c)^2\f$
|
||||
* -# calculate the theory vector.
|
||||
* \brief Prepares RRF asymmetry data for plotting and visualization.
|
||||
*
|
||||
* \param runData raw run data needed to perform some crosschecks
|
||||
* \param histoNo histogram number (within a run). histoNo[0]: forward histogram number, histNo[1]: backward histogram number
|
||||
* Processes pre-grouped data for display in plots with RRF transformation and
|
||||
* special handling for visualization. Similar to PrepareFitData but includes
|
||||
* theory calculation with Kaiser FIR filtering for smooth RRF curves.
|
||||
*
|
||||
* Processing steps:
|
||||
* 1. Validates and estimates data range if needed
|
||||
* 2. Aligns forward/backward histogram start bins relative to t0
|
||||
* 3. Ensures equal bin counts between forward/backward
|
||||
* 4. Calculates standard asymmetry: \f$ A_i = (\alpha f_i^{\rm c} - b_i^{\rm c})/(\alpha \beta f_i^{\rm c} + b_i^{\rm c}) \f$
|
||||
* 5. Applies RRF transformation: \f$ A_{\rm RRF}(t) = A(t) \cdot 2\cos(\omega_{\rm RRF} t + \phi_{\rm RRF}) \f$
|
||||
* 6. Applies RRF packing for visualization
|
||||
* 7. Propagates errors: \f$ \delta A_i = \frac{2}{(f_i^{\rm c}+b_i^{\rm c})^2}\sqrt{(b_i^{\rm c})^2 (\delta f_i^{\rm c})^2 + (f_i^{\rm c})^2 (\delta b_i^{\rm c})^2} \f$
|
||||
* 8. Calculates theory curve at high resolution
|
||||
* 9. Applies RRF transformation to theory
|
||||
* 10. Applies Kaiser FIR filter to smooth theory curve
|
||||
*
|
||||
* The RRF frequency and phase are read from the PLOT block settings.
|
||||
*
|
||||
* \param runData Pointer to raw run data for validation and cross-checks
|
||||
* \param histoNo Array of histogram indices: [0]=forward, [1]=backward
|
||||
* \return True on success, false on error
|
||||
*/
|
||||
Bool_t PRunAsymmetryRRF::PrepareViewData(PRawRunData* runData, UInt_t histoNo[2])
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -42,7 +42,14 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor. Needed otherwise vector's cannot be generated ;-)
|
||||
* \brief Default constructor that initializes all member variables to default values.
|
||||
*
|
||||
* Creates an empty, invalid run object with all pointers set to nullptr and
|
||||
* values set to undefined/invalid states. This constructor is needed to allow
|
||||
* creation of vectors of PRunBase-derived objects.
|
||||
*
|
||||
* A run created with this constructor requires initialization via the main
|
||||
* constructor before it can be used for fitting.
|
||||
*/
|
||||
PRunBase::PRunBase()
|
||||
{
|
||||
@@ -64,12 +71,25 @@ PRunBase::PRunBase()
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor.
|
||||
* \brief Main constructor that initializes a run from MSR file and raw data.
|
||||
*
|
||||
* \param msrInfo pointer to the msr-file handler
|
||||
* \param rawData pointer to the raw-data handler
|
||||
* \param runNo msr-file run number
|
||||
* \param tag tag telling if fit, view, or rrf representation is whished.
|
||||
* Performs comprehensive initialization:
|
||||
* 1. Stores operation mode (fit vs. view) and pointers to MSR and data handlers
|
||||
* 2. Extracts run-specific settings from the appropriate MSR RUN block
|
||||
* 3. Validates function parameter mappings to ensure FUNCTIONS block is valid
|
||||
* 4. Initializes metadata structures (field, energy, temperature)
|
||||
* 5. Initializes function value cache for FUNCTIONS block evaluation
|
||||
* 6. Creates PTheory object for evaluating the theory function
|
||||
* 7. Validates that theory initialization succeeded
|
||||
*
|
||||
* If any initialization step fails (e.g., invalid theory, out-of-range parameters),
|
||||
* the program exits with an error message. The run object is marked as valid upon
|
||||
* successful completion.
|
||||
*
|
||||
* \param msrInfo Pointer to MSR file handler (must remain valid for object lifetime)
|
||||
* \param rawData Pointer to raw data handler (must remain valid for object lifetime)
|
||||
* \param runNo Run number (0-based index into MSR file RUN blocks)
|
||||
* \param tag Operation mode: kFit (fitting), kView (display/plotting)
|
||||
*/
|
||||
PRunBase::PRunBase(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t runNo, EPMusrHandleTag tag) :
|
||||
fHandleTag(tag), fMsrInfo(msrInfo), fRawData(rawData)
|
||||
@@ -118,7 +138,16 @@ PRunBase::PRunBase(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t runNo,
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor.
|
||||
* \brief Virtual destructor that cleans up allocated resources.
|
||||
*
|
||||
* Frees memory allocated for:
|
||||
* - t0 value vectors (fT0s)
|
||||
* - Additional run t0 vectors (fAddT0s)
|
||||
* - Function value cache (fFuncValues)
|
||||
*
|
||||
* The PTheory object is automatically deleted via unique_ptr.
|
||||
* Pointers to MSR handler and raw data handler are NOT deleted as they
|
||||
* are owned by the calling code.
|
||||
*/
|
||||
PRunBase::~PRunBase()
|
||||
{
|
||||
@@ -130,14 +159,81 @@ PRunBase::~PRunBase()
|
||||
fFuncValues.clear();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// DeadTimeCorrection (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* \brief carry out dead time correction
|
||||
*
|
||||
* \param histos histograms to be corrected
|
||||
* \param histoNo histogram numbers
|
||||
*/
|
||||
void PRunBase::DeadTimeCorrection(std::vector<PDoubleVector> &histos, PUIntVector &histoNo)
|
||||
{
|
||||
PRawRunData* runData = fRawData->GetRunData(*fRunInfo->GetRunName());
|
||||
|
||||
if (!runData->DeadTimeCorrectionReady()) {
|
||||
std::cerr << std::endl << "**WARNING** PRunBase::DeadTimeCorrection: missing input for dead time correction" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// check if a dead time correction has to be done
|
||||
// first check the global block
|
||||
TString dtcg = fMsrInfo->GetMsrGlobal()->GetDeadTimeCorrection();
|
||||
Int_t dtcg_tag = 0; // 0=no, 1=file, 2=estimate
|
||||
if (dtcg.Contains("file", TString::kIgnoreCase)) {
|
||||
dtcg_tag = 1;
|
||||
} else if (dtcg.Contains("estimate", TString::kIgnoreCase)) {
|
||||
dtcg_tag = 2;
|
||||
}
|
||||
// now check each run
|
||||
TString dtcr{"no"};
|
||||
Bool_t needToCheck{true};
|
||||
for (UInt_t i=0; i<histoNo.size(); i++) {
|
||||
dtcr = fRunInfo->GetDeadTimeCorrection();
|
||||
if (dtcr.Contains("file", TString::kIgnoreCase) || (dtcg_tag != 0)) {
|
||||
if (runData->DeadTimeCorrectionReady()) {
|
||||
needToCheck = false;
|
||||
// Dead time correction: n_true = n_obs / (1 - n_obs * t_dt / (good_frames * dt))
|
||||
Double_t n_true;
|
||||
Int_t gf = runData->GetNumberOfGoodFrames();
|
||||
std::vector<float> t_dt = runData->GetDeadTimeParam();
|
||||
for (UInt_t j=0; j<histos[i].size(); j++) {
|
||||
n_true = histos[i][j] / (1.0 - histos[i][j] * t_dt[histoNo[i]] / (gf * fTimeResolution));
|
||||
histos[i][j] = n_true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((dtcr.Contains("estimate", TString::kIgnoreCase) || (dtcg_tag != 0)) && needToCheck) {
|
||||
std::cerr << std::endl << "**INFO** deadtime correction estimate not yet implemented." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// SetFitRange (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p> Sets the current fit range, and recalculated the number of fitted bins
|
||||
* \brief Sets the fit time range and recalculates the number of fitted bins.
|
||||
*
|
||||
* \param fitRange vector with fit ranges
|
||||
* Updates the fitting window for this run. This method handles two scenarios:
|
||||
* 1. Single fit range: If fitRange contains one pair, it applies to all runs
|
||||
* 2. Multiple fit ranges: If fitRange contains multiple pairs, it selects the
|
||||
* appropriate range based on fRunNo
|
||||
*
|
||||
* The method validates that:
|
||||
* - The fit range vector is not empty (asserts)
|
||||
* - The run number is within the fit range vector bounds
|
||||
* - Start time is before end time (swaps if not)
|
||||
*
|
||||
* This is typically called by the FIT_RANGE command to dynamically adjust the
|
||||
* fitting window during optimization or range scanning.
|
||||
*
|
||||
* \param fitRange Vector of (start, end) time pairs in microseconds (μs)
|
||||
*
|
||||
* Example: fitRange = {(0.1, 10.0), (0.2, 8.0)} applies first range to run 0,
|
||||
* second range to run 1
|
||||
*/
|
||||
void PRunBase::SetFitRange(PDoublePairVector fitRange)
|
||||
{
|
||||
@@ -177,7 +273,13 @@ void PRunBase::SetFitRange(PDoublePairVector fitRange)
|
||||
// CleanUp (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p> Clean up all locally allocate memory
|
||||
* \brief Cleans up allocated resources.
|
||||
*
|
||||
* Releases memory used by the PTheory object via unique_ptr reset.
|
||||
* This is called when the run processing is complete or when preparing
|
||||
* for a new fit with different settings.
|
||||
*
|
||||
* Other data structures (vectors) are managed automatically by their destructors.
|
||||
*/
|
||||
void PRunBase::CleanUp()
|
||||
{
|
||||
@@ -188,14 +290,37 @@ void PRunBase::CleanUp()
|
||||
// CalculateKaiserFilterCoeff (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculates the Kaiser filter coefficients for a low pass filter with
|
||||
* a cut off frequency wc.
|
||||
* For details see "Zeitdiskrete Signalverarbeitung", A.V. Oppenheim, R.W. Schafer, J.R. Buck. Pearson 2004.
|
||||
* \brief Calculates Kaiser window FIR filter coefficients for RRF smoothing.
|
||||
*
|
||||
* \param wc cut off frequency
|
||||
* \param A defined as \f$ A = -\log_{10}(\delta) \f$, where \f$\delta\f$ is the tolerance band.
|
||||
* \param dw defined as \f$ \Delta\omega = \omega_{\rm S} - \omega_{\rm P} \f$, where \f$ \omega_{\rm S} \f$ is the
|
||||
* stop band frequency, and \f$ \omega_{\rm P} \f$ is the pass band frequency.
|
||||
* Designs a low-pass FIR filter using the Kaiser window method, which provides
|
||||
* excellent control over the frequency response characteristics. The filter is
|
||||
* used to smooth theory curves in rotating reference frame (RRF) fits, ensuring
|
||||
* consistent comparison between filtered data and filtered theory.
|
||||
*
|
||||
* Algorithm (based on Oppenheim, Schafer, Buck, "Discrete-Time Signal Processing"):
|
||||
* 1. Determine β parameter from attenuation requirement A
|
||||
* 2. Calculate filter order m from transition width dw
|
||||
* 3. Generate Kaiser window: \f$ w[n] = \frac{I_0(\beta\sqrt{1-(n/\alpha)^2})}{I_0(\beta)} \f$
|
||||
* 4. Apply window to ideal sinc filter: \f$ h[n] = \frac{\sin(\omega_c n)}{\pi n} \cdot w[n] \f$
|
||||
* 5. Normalize coefficients to unity gain at DC
|
||||
*
|
||||
* The β parameter is chosen based on attenuation A (in dB):
|
||||
* - A > 50: β = 0.1102(A - 8.7)
|
||||
* - 21 ≤ A ≤ 50: β = 0.5842(A - 21)^0.4 + 0.07886(A - 21)
|
||||
* - A < 21: β = 0
|
||||
*
|
||||
* Filter order: m = (A - 8) / (2.285 × Δω × π), rounded to nearest odd integer
|
||||
*
|
||||
* Reference: A.V. Oppenheim, R.W. Schafer, J.R. Buck,
|
||||
* "Discrete-Time Signal Processing", Pearson 2004, pp. 574ff
|
||||
*
|
||||
* \param wc Cutoff frequency (normalized, 0 to π rad/sample)
|
||||
* \param A Attenuation in dB: A = -20 log₁₀(δ) where δ is the tolerance band
|
||||
* \param dw Transition width: Δω = ω_S - ω_P (stop band - pass band frequencies)
|
||||
*
|
||||
* The computed coefficients are stored in fKaiserFilter and normalized for unity DC gain.
|
||||
*
|
||||
* \see FilterTheo() for application of these coefficients
|
||||
*/
|
||||
void PRunBase::CalculateKaiserFilterCoeff(Double_t wc, Double_t A, Double_t dw)
|
||||
{
|
||||
@@ -235,7 +360,33 @@ void PRunBase::CalculateKaiserFilterCoeff(Double_t wc, Double_t A, Double_t dw)
|
||||
// FilterTheo (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Filters the theory with a Kaiser FIR filter.
|
||||
* \brief Applies Kaiser FIR filter to theory values for RRF fits.
|
||||
*
|
||||
* Performs time-domain convolution of the theory function with the Kaiser filter
|
||||
* coefficients computed by CalculateKaiserFilterCoeff(). This smooths the theory
|
||||
* curve to match the filtering applied to RRF-transformed data, ensuring fair
|
||||
* comparison during χ² calculation.
|
||||
*
|
||||
* The filtering operation is:
|
||||
* \f[ y_{\rm filtered}[i] = \sum_{j=0}^{M-1} h[j] \cdot y_{\rm theory}[i-j] \f]
|
||||
*
|
||||
* where:
|
||||
* - h[j] are the Kaiser filter coefficients from fKaiserFilter
|
||||
* - M is the filter length
|
||||
* - For i < j, the missing samples are treated as zero (causal filter)
|
||||
*
|
||||
* Additional processing:
|
||||
* - The filtered theory replaces the original theory in fData
|
||||
* - Time start is shifted backward by half the filter length to compensate
|
||||
* for the group delay introduced by the symmetric FIR filter
|
||||
*
|
||||
* This method is only called by RRF-derived classes (PRunAsymmetryRRF, PRunSingleHistoRRF)
|
||||
* after theory calculation and RRF transformation.
|
||||
*
|
||||
* \pre CalculateKaiserFilterCoeff() must have been called to initialize fKaiserFilter
|
||||
* \pre fData must contain theory values (CalcTheory() must have been called)
|
||||
*
|
||||
* \see CalculateKaiserFilterCoeff() for filter coefficient calculation
|
||||
*/
|
||||
void PRunBase::FilterTheo()
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -35,10 +35,28 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor.
|
||||
* \brief Constructor initializing the run collection manager.
|
||||
*
|
||||
* \param msrInfo pointer to the msr-file handler
|
||||
* \param data pointer to the run-data handler
|
||||
* Creates an empty collection ready to receive processed run objects via Add() calls.
|
||||
* The collection maintains separate lists for each fit type (single histogram, asymmetry,
|
||||
* RRF variants, etc.) and dispatches operations to the appropriate lists.
|
||||
*
|
||||
* Initialization:
|
||||
* - Stores pointers to MSR file handler and raw data handler (not owned)
|
||||
* - Sets theory calculation mode flag (for plotting vs. fitting)
|
||||
* - All run lists start empty; populated via subsequent Add() calls
|
||||
*
|
||||
* The typical workflow is:
|
||||
* 1. Create PRunListCollection
|
||||
* 2. Call Add() for each RUN block in MSR file
|
||||
* 3. Use Get*Chisq() or Get*MaximumLikelihood() during fitting
|
||||
* 4. Use Get*() accessors for visualization and analysis
|
||||
*
|
||||
* \param msrInfo Pointer to MSR file handler (must remain valid for object lifetime)
|
||||
* \param data Pointer to raw data handler for loading histogram files
|
||||
* \param theoAsData Theory calculation mode: true = at data points only, false = high-resolution grid
|
||||
*
|
||||
* \see Add() for adding processed runs to the collection
|
||||
*/
|
||||
PRunListCollection::PRunListCollection(PMsrHandler *msrInfo, PRunDataHandler *data, Bool_t theoAsData) :
|
||||
fMsrInfo(msrInfo), fData(data), fTheoAsData(theoAsData)
|
||||
@@ -49,7 +67,24 @@ PRunListCollection::PRunListCollection(PMsrHandler *msrInfo, PRunDataHandler *da
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor
|
||||
* \brief Destructor that cleans up all run objects.
|
||||
*
|
||||
* Systematically destroys all PRunBase-derived objects in the collection:
|
||||
* 1. Calls CleanUp() on each run object to release internal resources
|
||||
* 2. Explicitly calls destructor to free memory
|
||||
* 3. Clears the vector to release the pointer storage
|
||||
*
|
||||
* This process is repeated for all seven run type lists:
|
||||
* - Single histogram runs
|
||||
* - Single histogram RRF runs
|
||||
* - Asymmetry runs
|
||||
* - Asymmetry RRF runs
|
||||
* - β-NMR asymmetry runs
|
||||
* - μ⁻ (mu-minus) runs
|
||||
* - Non-μSR runs
|
||||
*
|
||||
* The MSR handler (fMsrInfo) and data handler (fData) are NOT deleted
|
||||
* as they are owned by the calling code.
|
||||
*/
|
||||
PRunListCollection::~PRunListCollection()
|
||||
{
|
||||
@@ -100,14 +135,35 @@ PRunListCollection::~PRunListCollection()
|
||||
// Add (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Adds a processed set of data to the handler.
|
||||
* \brief Adds a processed run to the appropriate list based on fit type.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if a processed data set could be added successfully
|
||||
* - false otherwise
|
||||
* Creates a new PRunBase-derived object for the specified MSR file RUN block and
|
||||
* adds it to the appropriate type-specific list. The method performs fit type
|
||||
* dispatching by:
|
||||
* 1. Reading fit type from the RUN block (if specified)
|
||||
* 2. Falling back to GLOBAL block fit type if not specified in RUN
|
||||
* 3. Creating the appropriate run object based on fit type
|
||||
* 4. Calling PrepareData() on the new object to load and process data
|
||||
* 5. Checking validity and returning success/failure status
|
||||
*
|
||||
* \param runNo msr-file run number
|
||||
* \param tag tag showing what shall be done: kFit == fitting, kView == viewing
|
||||
* Supported fit types and corresponding classes:
|
||||
* - PRUN_SINGLE_HISTO → PRunSingleHisto
|
||||
* - PRUN_SINGLE_HISTO_RRF → PRunSingleHistoRRF
|
||||
* - PRUN_ASYMMETRY → PRunAsymmetry
|
||||
* - PRUN_ASYMMETRY_RRF → PRunAsymmetryRRF
|
||||
* - PRUN_ASYMMETRY_BNMR → PRunAsymmetryBNMR
|
||||
* - PRUN_MU_MINUS → PRunMuMinus
|
||||
* - PRUN_NON_MUSR → PRunNonMusr
|
||||
*
|
||||
* If data preprocessing fails (e.g., file not found, invalid t0, theory errors),
|
||||
* the run object is still added to the list but marked as invalid, and this
|
||||
* method returns false.
|
||||
*
|
||||
* \param runNo MSR file run number (0-based index into RUN blocks)
|
||||
* \param tag Operation mode: kFit (for fitting), kView (for display/plotting)
|
||||
* \return True if run was added and initialized successfully, false if initialization failed
|
||||
*
|
||||
* \see PRunBase::PrepareData() for data preprocessing details
|
||||
*/
|
||||
Bool_t PRunListCollection::Add(Int_t runNo, EPMusrHandleTag tag)
|
||||
{
|
||||
@@ -167,15 +223,32 @@ Bool_t PRunListCollection::Add(Int_t runNo, EPMusrHandleTag tag)
|
||||
// SetFitRange (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Set the current fit range in bins. The string has the structure:
|
||||
* 'fit_range fgb0+n00 lgb0-n01 [fgb1+n10 lgb-n11 fgb2+n20 lgb2-n21 .. fgbN+nN0 lgbN-nN1]'
|
||||
* where fgb is the first good bin, lgb is the last good bin. nXY are offsets in bins.
|
||||
* N is the number of runs in the msr-file.
|
||||
* \brief Sets fit range in bin units using string specification (COMMANDS block syntax).
|
||||
*
|
||||
* <p>This means there are 2 options: (i) a globle fit range in bins for <em>all</em> runs in the
|
||||
* msr-file, or (ii) each run block in the msr-file needs its individual range.
|
||||
* Parses and applies fit range specified in bin offsets from t0 markers.
|
||||
* This method supports the COMMANDS block FIT_RANGE syntax used for dynamic
|
||||
* range adjustments during optimization.
|
||||
*
|
||||
* \param fitRange string holding the fit range(s).
|
||||
* String format:
|
||||
* - Single range: "fit_range fgb+n0 lgb-n1"
|
||||
* - Multiple ranges: "fit_range fgb0+n00 lgb0-n01 fgb1+n10 lgb1-n11 ..."
|
||||
*
|
||||
* Where:
|
||||
* - fgb = first good bin (t0 marker from MSR file)
|
||||
* - lgb = last good bin (end marker, often from data_range or automatic)
|
||||
* - nXY = offset in bins (can be positive or negative)
|
||||
*
|
||||
* Example:
|
||||
* - "fit_range fgb+10 lgb-20" → Start 10 bins after t0, end 20 bins before last good bin
|
||||
* - For multiple runs, each gets its own fgb/lgb pair in sequence
|
||||
*
|
||||
* This method broadcasts the range specification to all run objects in all lists.
|
||||
* Each run's SetFitRangeBin() method interprets the string based on its position
|
||||
* in the MSR file.
|
||||
*
|
||||
* \param fitRange String holding fit range specification in bin offsets
|
||||
*
|
||||
* \see SetFitRange(PDoublePairVector) for time-based range specification
|
||||
*/
|
||||
void PRunListCollection::SetFitRange(const TString fitRange)
|
||||
{
|
||||
@@ -199,11 +272,33 @@ void PRunListCollection::SetFitRange(const TString fitRange)
|
||||
// SetFitRange (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Set the current fit range in time. If fitRange.size()==1 the given fit range will be used for all the runs,
|
||||
* otherwise fitRange.size()==the number of runs in the msr-file, and for each run there will be an individual
|
||||
* fit range.
|
||||
* \brief Sets fit range in time units (microseconds from t0).
|
||||
*
|
||||
* \param fitRange vector holding the fit range(s).
|
||||
* Applies time-based fit ranges to all runs in the collection. This is the
|
||||
* standard method for specifying fit ranges in the MSR file FIT block or
|
||||
* during interactive range adjustments.
|
||||
*
|
||||
* Range specification modes:
|
||||
* - <b>Global range:</b> fitRange.size() == 1
|
||||
* - Same (start, end) time pair applies to all runs
|
||||
* - Example: {(0.1, 10.0)} → All runs fit from 0.1 μs to 10.0 μs after t0
|
||||
*
|
||||
* - <b>Individual ranges:</b> fitRange.size() == number of MSR file runs
|
||||
* - Each run gets its own (start, end) time pair
|
||||
* - fitRange[i] corresponds to MSR file RUN block i
|
||||
* - Example: {(0.1, 10.0), (0.2, 8.0)} → Run 0: 0.1-10.0 μs, Run 1: 0.2-8.0 μs
|
||||
*
|
||||
* Processing steps for each run:
|
||||
* 1. SetFitRange() updates internal start/end time members
|
||||
* 2. CalcNoOfFitBins() recalculates bin indices (fStartTimeBin, fEndTimeBin)
|
||||
*
|
||||
* The bin recalculation is necessary because the fit range is initially specified
|
||||
* in time but χ² calculation operates on bin indices.
|
||||
*
|
||||
* \param fitRange Vector of (start_time, end_time) pairs in microseconds (μs) from t0
|
||||
*
|
||||
* \see SetFitRange(TString) for bin-based range specification
|
||||
* \see PRunBase::CalcNoOfFitBins() for time-to-bin conversion
|
||||
*/
|
||||
void PRunListCollection::SetFitRange(const PDoublePairVector fitRange)
|
||||
{
|
||||
@@ -239,12 +334,21 @@ void PRunListCollection::SetFitRange(const PDoublePairVector fitRange)
|
||||
// GetSingleHistoChisq (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculates chi-square of <em>all</em> single histogram runs of a msr-file.
|
||||
* \brief Calculates total χ² for all single histogram runs (global fit metric).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chi-square of all single histogram runs of the msr-file
|
||||
* Sums the chi-squared statistic over all single histogram runs in the collection:
|
||||
* \f[ \chi^2_{\rm total} = \sum_{i=1}^{N_{\rm runs}} \chi^2_i \f]
|
||||
*
|
||||
* \param par fit parameter vector
|
||||
* where each run's χ² is:
|
||||
* \f[ \chi^2_i = \sum_{j=1}^{N_{\rm bins,i}} \frac{(y_j^{\rm data} - y_j^{\rm theory})^2}{\sigma_j^2} \f]
|
||||
*
|
||||
* This is the objective function minimized by MINUIT during global fitting of
|
||||
* multiple single histogram runs. Called repeatedly during each fit iteration.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT with current parameter values
|
||||
* \return Total χ² summed over all single histogram runs
|
||||
*
|
||||
* \see PRunSingleHisto::CalcChiSquare() for per-run χ² calculation
|
||||
*/
|
||||
Double_t PRunListCollection::GetSingleHistoChisq(const std::vector<Double_t>& par) const
|
||||
{
|
||||
@@ -281,12 +385,19 @@ Double_t PRunListCollection::GetSingleHistoRRFChisq(const std::vector<Double_t>&
|
||||
// GetAsymmetryChisq (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculates chi-square of <em>all</em> asymmetry runs of a msr-file.
|
||||
* \brief Calculates total χ² for all asymmetry runs (global fit metric).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chi-square of all asymmetry runs of the msr-file
|
||||
* Sums the chi-squared statistic over all asymmetry runs in the collection.
|
||||
* For asymmetry fits, χ² is calculated from the asymmetry values:
|
||||
* \f[ A_i = \frac{F_i - \alpha B_i}{F_i + \alpha B_i} \f]
|
||||
*
|
||||
* \param par fit parameter vector
|
||||
* with proper error propagation. This is the objective function for global
|
||||
* asymmetry fits involving multiple runs (e.g., temperature or field scans).
|
||||
*
|
||||
* \param par Parameter vector from MINUIT with current parameter values
|
||||
* \return Total χ² summed over all asymmetry runs
|
||||
*
|
||||
* \see PRunAsymmetry::CalcChiSquare() for per-run asymmetry χ² calculation
|
||||
*/
|
||||
Double_t PRunListCollection::GetAsymmetryChisq(const std::vector<Double_t>& par) const
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -47,7 +47,19 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Default constructor creating an empty, invalid μ⁻ run object.
|
||||
*
|
||||
* Initializes all member variables to default/invalid states:
|
||||
* - Bin counts and indices set to -1 (invalid)
|
||||
* - Packing set to -1 (unspecified - will cause error if used)
|
||||
* - Theory mode set to false (high-resolution grid)
|
||||
* - Handle tag set to kEmpty (uninitialized)
|
||||
*
|
||||
* This constructor is needed for creating vectors of PRunMuMinus objects,
|
||||
* but the resulting object cannot be used for fitting until properly
|
||||
* initialized via the main constructor.
|
||||
*
|
||||
* \see PRunMuMinus(PMsrHandler*, PRunDataHandler*, UInt_t, EPMusrHandleTag, Bool_t)
|
||||
*/
|
||||
PRunMuMinus::PRunMuMinus() : PRunBase()
|
||||
{
|
||||
@@ -70,12 +82,43 @@ PRunMuMinus::PRunMuMinus() : PRunBase()
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Main constructor initializing a μ⁻ run from MSR file and raw data.
|
||||
*
|
||||
* \param msrInfo pointer to the msr-file handler
|
||||
* \param rawData raw run data
|
||||
* \param runNo number of the run within the msr-file
|
||||
* \param tag tag showing what shall be done: kFit == fitting, kView == viewing
|
||||
* Performs comprehensive initialization for negative muon analysis:
|
||||
*
|
||||
* 1. <b>Base Class Initialization:</b>
|
||||
* - Calls PRunBase constructor with MSR/data handlers
|
||||
* - Initializes theory engine and parameter mappings
|
||||
*
|
||||
* 2. <b>Packing Validation (CRITICAL for μ⁻):</b>
|
||||
* - Attempts to read packing from RUN block
|
||||
* - Falls back to GLOBAL block if not in RUN block
|
||||
* - SEVERE ERROR if packing == -1 (unspecified)
|
||||
* - Packing is MANDATORY for μ⁻ data (unlike some other fit types)
|
||||
*
|
||||
* 3. <b>Member Initialization:</b>
|
||||
* - Good bin markers set to -1 (determined later)
|
||||
* - Fit range bins initialized to -1 (invalid until set)
|
||||
* - Number of fit bins set to 0
|
||||
*
|
||||
* 4. <b>Data Preparation:</b>
|
||||
* - Calls PrepareData() to load and preprocess histogram
|
||||
* - If PrepareData() fails, run is marked invalid
|
||||
*
|
||||
* The object is marked as invalid (fValid=false) if:
|
||||
* - Packing parameter is missing
|
||||
* - PrepareData() fails (file not found, invalid t0, etc.)
|
||||
*
|
||||
* \param msrInfo Pointer to MSR file handler (must remain valid for object lifetime)
|
||||
* \param rawData Pointer to raw data handler for loading histogram files
|
||||
* \param runNo Run number (0-based index in MSR file RUN blocks)
|
||||
* \param tag Operation mode: kFit (fitting), kView (display/plotting)
|
||||
* \param theoAsData Theory calculation mode: true = at data points, false = high-resolution
|
||||
*
|
||||
* \warning Invalid objects should not be used for fitting. Check IsValid() after construction.
|
||||
*
|
||||
* \see PrepareData() for data preprocessing details
|
||||
* \see PRunBase constructor for base initialization
|
||||
*/
|
||||
PRunMuMinus::PRunMuMinus(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t runNo, EPMusrHandleTag tag, Bool_t theoAsData) :
|
||||
PRunBase(msrInfo, rawData, runNo, tag), fTheoAsData(theoAsData)
|
||||
@@ -114,7 +157,10 @@ PRunMuMinus::PRunMuMinus(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor
|
||||
* \brief Destructor cleaning up allocated resources.
|
||||
*
|
||||
* Releases memory used by the forward histogram vector. Other cleanup
|
||||
* (theory objects, base class resources) is handled by the PRunBase destructor.
|
||||
*/
|
||||
PRunMuMinus::~PRunMuMinus()
|
||||
{
|
||||
@@ -125,12 +171,38 @@ PRunMuMinus::~PRunMuMinus()
|
||||
// CalcChiSquare
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate chi-square.
|
||||
* \brief Calculates χ² between μ⁻ data and theory (least-squares fit metric).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value
|
||||
* Computes the chi-squared statistic using the standard formula:
|
||||
* \f[ \chi^2 = \sum_{i={\rm start}}^{\rm end} \frac{(N_i^{\rm data} - N_i^{\rm theory})^2}{\sigma_i^2} \f]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* Algorithm:
|
||||
* 1. Evaluate FUNCTIONS block for user-defined functions
|
||||
* 2. Pre-calculate theory once at t=1.0 (thread-safe initialization for LF/user functions)
|
||||
* 3. Loop over fit range bins (fStartTimeBin to fEndTimeBin)
|
||||
* 4. For each bin:
|
||||
* - Calculate time from bin index
|
||||
* - Evaluate theory function at that time
|
||||
* - Compute squared difference weighted by error
|
||||
* 5. Sum contributions (with OpenMP reduction if available)
|
||||
*
|
||||
* <b>OpenMP Parallelization:</b>
|
||||
* - When compiled with GOMP support, χ² calculation is parallelized
|
||||
* - Loop divided into dynamic chunks for load balancing
|
||||
* - Chunk size: (N_bins / N_processors), minimum 10 bins per chunk
|
||||
* - Private variables per thread: i, time, diff
|
||||
* - Reduction performed on final chisq sum
|
||||
*
|
||||
* <b>Theory Pre-calculation:</b>
|
||||
* The initial call to fTheory->Func(time=1.0, ...) ensures thread-safe
|
||||
* initialization for London field (LF) and user functions that cache
|
||||
* computationally expensive calculations per parameter set.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT with current parameter values
|
||||
* \return Chi-squared value (sum of weighted squared residuals)
|
||||
*
|
||||
* \see CalcMaxLikelihood() for Poisson-based alternative (better for low counts)
|
||||
* \see CalcTheory() for theory evaluation without χ² calculation
|
||||
*/
|
||||
Double_t PRunMuMinus::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -172,12 +244,33 @@ Double_t PRunMuMinus::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
// CalcChiSquareExpected (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate expected chi-square.
|
||||
* \brief Calculates expected χ² assuming theory is the true distribution (diagnostic).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value == 0.0
|
||||
* Computes the expected chi-squared using theory values as the expected counts:
|
||||
* \f[ \chi^2_{\rm expected} = \sum_{i} \frac{(N_i^{\rm data} - N_i^{\rm theory})^2}{N_i^{\rm theory}} \f]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* This is a statistical diagnostic for evaluating:
|
||||
* - Quality of error estimates (if errors are correct, χ²/ν ≈ 1)
|
||||
* - Validity of Gaussian approximation (breaks down for low counts)
|
||||
* - Over/under-dispersion in data relative to Poisson expectations
|
||||
*
|
||||
* For Poisson-distributed data with large counts:
|
||||
* - χ²_expected ≈ number of degrees of freedom
|
||||
* - χ²_expected / ν ≈ 1 indicates proper error estimation
|
||||
*
|
||||
* Algorithm is identical to CalcChiSquare() except:
|
||||
* - Error denominator is σ² = N_theory (Poisson variance)
|
||||
* - Instead of using fData.GetError()->at(i)
|
||||
*
|
||||
* <b>OpenMP Parallelization:</b> Same as CalcChiSquare()
|
||||
*
|
||||
* \param par Parameter vector from MINUIT
|
||||
* \return Expected χ² value (currently returns 0.0 - calculation done but not returned)
|
||||
*
|
||||
* \note Current implementation performs the calculation but returns 0.0.
|
||||
* The calculated value could be returned for diagnostic purposes.
|
||||
*
|
||||
* \see CalcChiSquare() for standard χ² calculation
|
||||
*/
|
||||
Double_t PRunMuMinus::CalcChiSquareExpected(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -221,12 +314,48 @@ Double_t PRunMuMinus::CalcChiSquareExpected(const std::vector<Double_t>& par)
|
||||
// CalcMaxLikelihood
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate log max-likelihood. See http://pdg.lbl.gov/index.html
|
||||
* \brief Calculates negative log-likelihood for Poisson statistics (low-count fit metric).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - log max-likelihood value
|
||||
* Computes the maximum likelihood estimator assuming Poisson-distributed histogram counts:
|
||||
* \f[ -2\ln L = 2\sum_{i} \left[N_i^{\rm theory} - N_i^{\rm data}\ln(N_i^{\rm theory})\right] \f]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* This is derived from the Poisson probability:
|
||||
* \f[ P(n|\\lambda) = \frac{\\lambda^n e^{-\\lambda}}{n!} \f]
|
||||
*
|
||||
* Taking negative log-likelihood and multiplying by 2 gives a metric that:
|
||||
* - Is minimized at the best-fit parameters (like χ²)
|
||||
* - Approaches χ² in the high-count (Gaussian) limit
|
||||
* - Handles low counts correctly (no Gaussian approximation needed)
|
||||
*
|
||||
* <b>When to use likelihood vs. χ²:</b>
|
||||
* - <b>Low counts (< 10-20 per bin):</b> Use likelihood (this method)
|
||||
* - <b>High counts (> 20 per bin):</b> Either method works, χ² is faster
|
||||
* - <b>Uncertain errors:</b> Use likelihood (no error estimates needed)
|
||||
*
|
||||
* Algorithm:
|
||||
* 1. Evaluate FUNCTIONS block
|
||||
* 2. Pre-calculate theory at t=1.0 (thread-safe initialization)
|
||||
* 3. Loop over fit range bins
|
||||
* 4. For each bin:
|
||||
* - Calculate theory prediction
|
||||
* - Check for negative theory (warning + skip)
|
||||
* - Add Poisson likelihood term:
|
||||
* - If data > 10^-9: (theo - data) + data·ln(data/theo)
|
||||
* - If data ≈ 0: (theo - data) only (avoid log(0))
|
||||
* 5. Multiply sum by 2 (convention for comparison with χ²)
|
||||
*
|
||||
* <b>Edge Case Handling:</b>
|
||||
* - Negative theory: Print warning, skip bin (should not happen with proper model)
|
||||
* - Zero data: Use simplified formula without log term
|
||||
* - Zero theory: Would cause log(0), but checked via negative theory guard
|
||||
*
|
||||
* Reference: Particle Data Group (PDG), Statistics Review
|
||||
* http://pdg.lbl.gov/index.html
|
||||
*
|
||||
* \param par Parameter vector from MINUIT
|
||||
* \return -2×ln(L) value (minimize during fitting, comparable to χ²)
|
||||
*
|
||||
* \see CalcChiSquare() for standard least-squares metric
|
||||
*/
|
||||
Double_t PRunMuMinus::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -282,9 +411,19 @@ Double_t PRunMuMinus::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
// GetNoOfFitBins (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the number of fitted bins for the current fit range.
|
||||
* \brief Returns the number of bins included in the fit range.
|
||||
*
|
||||
* <b>return:</b> number of fitted bins.
|
||||
* Recalculates and returns the count of histogram bins between fStartTimeBin
|
||||
* and fEndTimeBin. This count is used for:
|
||||
* - Degrees of freedom calculation: ν = N_bins - N_params
|
||||
* - Reduced χ²: χ²_red = χ² / ν
|
||||
* - Statistical quality assessment
|
||||
*
|
||||
* Internally calls CalcNoOfFitBins() to ensure fNoOfFitBins is up-to-date.
|
||||
*
|
||||
* \return Number of bins within fit range (fEndTimeBin - fStartTimeBin)
|
||||
*
|
||||
* \see CalcNoOfFitBins() for bin range calculation from time range
|
||||
*/
|
||||
UInt_t PRunMuMinus::GetNoOfFitBins()
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -35,7 +35,21 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor.
|
||||
* \brief Default constructor creating an empty, invalid non-μSR run object.
|
||||
*
|
||||
* Initializes all member variables to default/safe values:
|
||||
* - fNoOfFitBins = 0 (no bins to fit)
|
||||
* - fPacking = 1 (no data averaging)
|
||||
* - fStartTimeBin = 0 (first data point)
|
||||
* - fEndTimeBin = 0 (no range)
|
||||
* - fHandleTag = kEmpty (uninitialized)
|
||||
* - fRawRunData = nullptr (no data loaded)
|
||||
*
|
||||
* This constructor is needed for creating vectors of PRunNonMusr objects.
|
||||
* The resulting object cannot be used until properly initialized via the
|
||||
* main constructor.
|
||||
*
|
||||
* \see PRunNonMusr(PMsrHandler*, PRunDataHandler*, UInt_t, EPMusrHandleTag, Bool_t)
|
||||
*/
|
||||
PRunNonMusr::PRunNonMusr() : PRunBase()
|
||||
{
|
||||
@@ -53,12 +67,48 @@ PRunNonMusr::PRunNonMusr() : PRunBase()
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Main constructor initializing a non-μSR run from MSR file and x-y data.
|
||||
*
|
||||
* \param msrInfo pointer to the msr-file handler
|
||||
* \param rawData raw run data
|
||||
* \param runNo number of the run within the msr-file
|
||||
* \param tag tag showing what shall be done: kFit == fitting, kView == viewing
|
||||
* Performs comprehensive initialization for general curve fitting:
|
||||
*
|
||||
* 1. <b>Base Class Initialization:</b>
|
||||
* - Calls PRunBase constructor with MSR/data handlers
|
||||
* - Initializes theory engine and parameter mappings
|
||||
* - Sets up FUNCTIONS block evaluation
|
||||
*
|
||||
* 2. <b>Raw Data Loading:</b>
|
||||
* - Retrieves raw x-y data using run name from MSR file
|
||||
* - Calls fRawData->GetRunData(*runName)
|
||||
* - Validates data was successfully loaded
|
||||
* - If loading fails → marks run invalid, prints error
|
||||
*
|
||||
* 3. <b>Data Preparation:</b>
|
||||
* - Calls PrepareData() to process x-y data
|
||||
* - Extracts x-y columns based on MSR file specification
|
||||
* - Applies packing to average data points
|
||||
* - Sets up fit range boundaries
|
||||
* - If preparation fails → marks run invalid
|
||||
*
|
||||
* The object is marked as invalid (fValid=false) if:
|
||||
* - Raw data file cannot be loaded (file not found, wrong format, etc.)
|
||||
* - PrepareData() fails (invalid column indices, missing packing, etc.)
|
||||
*
|
||||
* Key features for non-μSR:
|
||||
* - No histogram processing (data is already x-y pairs)
|
||||
* - No time-zero determination (not time-differential)
|
||||
* - No background subtraction (included in y-data)
|
||||
* - No asymmetry calculation (direct y vs. x fitting)
|
||||
*
|
||||
* \param msrInfo Pointer to MSR file handler (must remain valid for object lifetime)
|
||||
* \param rawData Pointer to raw data handler for loading data files
|
||||
* \param runNo Run number (0-based index in MSR file RUN blocks)
|
||||
* \param tag Operation mode: kFit (fitting), kView (display/plotting)
|
||||
* \param theoAsData Theory mode: true = at data x-values, false = high-resolution (minimal effect for non-μSR)
|
||||
*
|
||||
* \warning Always check IsValid() after construction before using for fitting
|
||||
*
|
||||
* \see PrepareData() for data processing details
|
||||
* \see PRunBase constructor for base class initialization
|
||||
*/
|
||||
PRunNonMusr::PRunNonMusr(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t runNo, EPMusrHandleTag tag, Bool_t theoAsData) :
|
||||
PRunBase(msrInfo, rawData, runNo, tag), fTheoAsData(theoAsData)
|
||||
@@ -80,7 +130,15 @@ PRunNonMusr::PRunNonMusr(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor
|
||||
* \brief Destructor (no cleanup needed for non-μSR).
|
||||
*
|
||||
* The fRawRunData pointer is not owned by this class and is not deleted here.
|
||||
* It is managed by the PRunDataHandler and will be cleaned up externally.
|
||||
*
|
||||
* Base class destructor (PRunBase) handles cleanup of:
|
||||
* - Theory engine objects
|
||||
* - Parameter mapping structures
|
||||
* - Function value caches
|
||||
*/
|
||||
PRunNonMusr::~PRunNonMusr()
|
||||
{
|
||||
@@ -90,12 +148,43 @@ PRunNonMusr::~PRunNonMusr()
|
||||
// CalcChiSquare
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate chi-square.
|
||||
* \brief Calculates χ² between non-μSR x-y data and theory.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value
|
||||
* Computes the chi-squared statistic for general x-y data:
|
||||
* \f[ \chi^2 = \sum_{i={\rm start}}^{\rm end} \frac{(y_i - f(x_i))^2}{\sigma_i^2} \f]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* where:
|
||||
* - x_i is the independent variable (arbitrary units)
|
||||
* - y_i is the measured dependent variable
|
||||
* - f(x_i) is the theory function evaluated at x_i
|
||||
* - σ_i is the error on y_i (from data file)
|
||||
*
|
||||
* Algorithm:
|
||||
* 1. <b>Evaluate FUNCTIONS block:</b>
|
||||
* - Loop over user-defined functions
|
||||
* - Compute function values using current parameters
|
||||
* - Store in fFuncValues for use by theory
|
||||
*
|
||||
* 2. <b>Calculate χ² sum:</b>
|
||||
* - Loop from fStartTimeBin to fEndTimeBin (inclusive)
|
||||
* - For each data point i:
|
||||
* a. Get x-value: x = fData.GetX()->at(i)
|
||||
* b. Evaluate theory at x: theo = fTheory->Func(x, par, fFuncValues)
|
||||
* c. Get data and error: y = fData.GetValue()->at(i), σ = fData.GetError()->at(i)
|
||||
* d. Compute contribution: Δχ² = (y - theo)² / σ²
|
||||
* - Sum all contributions
|
||||
*
|
||||
* Key differences from μSR fits:
|
||||
* - x-axis is arbitrary (not necessarily time in μs)
|
||||
* - Theory evaluated on-demand (not pre-calculated on grid)
|
||||
* - Loop end is INCLUSIVE (i <= fEndTimeBin)
|
||||
* - No OpenMP parallelization (simpler, smaller data sets)
|
||||
*
|
||||
* \param par Parameter vector from MINUIT with current parameter values
|
||||
* \return Chi-squared value (minimize during fitting)
|
||||
*
|
||||
* \see CalcMaxLikelihood() - NOT IMPLEMENTED for non-μSR
|
||||
* \see PrepareData() for x-y data loading and fit range setup
|
||||
*/
|
||||
Double_t PRunNonMusr::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -122,12 +211,26 @@ Double_t PRunNonMusr::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
// CalcChiSquareExpected (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate expected chi-square. Currently not implemented since not clear what to be done.
|
||||
* \brief Calculates expected χ² (NOT IMPLEMENTED for non-μSR).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value == 0.0
|
||||
* This method is not implemented because the concept of "expected χ²" requires
|
||||
* knowledge of the underlying statistical distribution of the data, which is
|
||||
* not well-defined for general x-y data.
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* For μSR histogram data, the expected χ² can be calculated based on Poisson
|
||||
* statistics. For arbitrary non-μSR data, the appropriate statistical model
|
||||
* depends on the data source:
|
||||
* - Counting experiments → Poisson
|
||||
* - Averaged measurements → Gaussian
|
||||
* - Other experiments → problem-specific distributions
|
||||
*
|
||||
* Without knowing the data's statistical nature, a meaningful implementation
|
||||
* cannot be provided.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT (unused)
|
||||
* \return Always returns 0.0
|
||||
*
|
||||
* \note Prints "not implemented yet" message to stdout
|
||||
*/
|
||||
Double_t PRunNonMusr::CalcChiSquareExpected(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -140,12 +243,32 @@ Double_t PRunNonMusr::CalcChiSquareExpected(const std::vector<Double_t>& par)
|
||||
// CalcMaxLikelihood
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate log maximum-likelihood. Currently not implemented since not clear what to be done.
|
||||
* \brief Calculates maximum likelihood (NOT IMPLEMENTED for non-μSR).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - log maximum-likelihood value == 1.0
|
||||
* Maximum likelihood fitting is not implemented for general x-y data because:
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* 1. <b>Distribution-dependent:</b> The likelihood function depends on the
|
||||
* underlying statistical distribution of the data points, which varies:
|
||||
* - Poisson: For counting experiments (like μSR histograms)
|
||||
* - Gaussian: For averaged measurements with known errors
|
||||
* - Other: Problem-specific distributions (binomial, exponential, etc.)
|
||||
*
|
||||
* 2. <b>Gaussian case equivalence:</b> If errors are Gaussian, maximum likelihood
|
||||
* is mathematically equivalent to χ² minimization (already implemented).
|
||||
*
|
||||
* 3. <b>Implementation complexity:</b> Supporting arbitrary likelihood functions
|
||||
* would require users to specify the distribution, adding complexity without
|
||||
* clear benefit for most non-μSR applications.
|
||||
*
|
||||
* For general x-y data with Gaussian errors, use χ² fitting via CalcChiSquare().
|
||||
* For non-Gaussian statistics, users should implement custom fitting outside musrfit.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT (unused)
|
||||
* \return Always returns 1.0
|
||||
*
|
||||
* \note Prints "not implemented yet" message to stdout
|
||||
*
|
||||
* \see CalcChiSquare() for standard least-squares fitting (recommended for non-μSR)
|
||||
*/
|
||||
Double_t PRunNonMusr::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -158,7 +281,20 @@ Double_t PRunNonMusr::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
// CalcTheory
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate theory for a given set of fit-parameters.
|
||||
* \brief Evaluates theory function (empty implementation for non-μSR).
|
||||
*
|
||||
* For non-μSR data, theory calculation is performed on-demand within
|
||||
* CalcChiSquare() rather than pre-calculating and storing theory values.
|
||||
*
|
||||
* This design choice is made because:
|
||||
* - Theory is evaluated at arbitrary x-values from the data file
|
||||
* - No need for high-resolution theory grid (data defines x-points)
|
||||
* - Simpler and more efficient to evaluate during χ² loop
|
||||
* - Avoids storing redundant theory array
|
||||
*
|
||||
* This empty method exists solely to satisfy the PRunBase interface requirement.
|
||||
*
|
||||
* \see CalcChiSquare() for on-demand theory evaluation at each data point
|
||||
*/
|
||||
void PRunNonMusr::CalcTheory()
|
||||
{
|
||||
@@ -168,9 +304,28 @@ void PRunNonMusr::CalcTheory()
|
||||
// GetNoOfFitBins (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the number of fitted bins for the current fit range.
|
||||
* \brief Calculates and returns the number of x-y points within the fit range.
|
||||
*
|
||||
* <b>return:</b> number of fitted bins.
|
||||
* Counts data points where fFitStartTime ≤ x ≤ fFitEndTime (both inclusive).
|
||||
* This count is essential for:
|
||||
* - Degrees of freedom: ν = N_points - N_params
|
||||
* - Reduced χ²: χ²_red = χ² / ν
|
||||
* - Statistical quality assessment: χ²/ν ≈ 1 indicates good fit
|
||||
*
|
||||
* Algorithm:
|
||||
* 1. Reset counter: fNoOfFitBins = 0
|
||||
* 2. Loop through all x-values in fData.GetX()
|
||||
* 3. For each x-value:
|
||||
* - If fFitStartTime ≤ x ≤ fFitEndTime → increment counter
|
||||
* 4. Return final count
|
||||
*
|
||||
* The fit range (fFitStartTime, fFitEndTime) is specified in the MSR file
|
||||
* RUN or GLOBAL block "fit" entry, in the same units as the x-axis data.
|
||||
*
|
||||
* \return Number of data points within fit range
|
||||
*
|
||||
* \note This method recalculates the count each time it's called (not cached),
|
||||
* allowing for dynamic fit range changes.
|
||||
*/
|
||||
UInt_t PRunNonMusr::GetNoOfFitBins()
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -50,7 +50,17 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Default constructor for single histogram fitting class.
|
||||
*
|
||||
* Initializes all member variables to safe default values:
|
||||
* - fScaleN0AndBkg = true (normalize N₀ and background to 1/ns)
|
||||
* - fPacking = -1 (invalid until set from MSR file)
|
||||
* - fBackground = 0 (will be estimated or set from MSR file)
|
||||
* - fStartTimeBin / fEndTimeBin = -1 (calculated from fit range)
|
||||
* - fGoodBins[0,1] = -1 (calculated from data range)
|
||||
*
|
||||
* \warning This constructor creates an invalid object until initialized
|
||||
* with MSR file data. Use the full constructor for normal operation.
|
||||
*/
|
||||
PRunSingleHisto::PRunSingleHisto() : PRunBase()
|
||||
{
|
||||
@@ -73,12 +83,27 @@ PRunSingleHisto::PRunSingleHisto() : PRunBase()
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Main constructor for single histogram fitting and viewing.
|
||||
*
|
||||
* \param msrInfo pointer to the msr-file handler
|
||||
* \param rawData raw run data
|
||||
* \param runNo number of the run within the msr-file
|
||||
* \param tag tag showing what shall be done: kFit == fitting, kView == viewing
|
||||
* Constructs a fully initialized single histogram run object by:
|
||||
* -# Extracting packing value from RUN block (or falling back to GLOBAL block)
|
||||
* -# Determining if N₀ and background should be scaled to 1/ns
|
||||
* -# Calling PrepareData() to load and process histogram data
|
||||
* -# Setting up fit ranges and background estimation
|
||||
*
|
||||
* \param msrInfo Pointer to MSR file handler (NOT owned, must outlive this object)
|
||||
* \param rawData Pointer to raw run data handler (NOT owned, must outlive this object)
|
||||
* \param runNo Zero-based index of the RUN block in the MSR file
|
||||
* \param tag Operation mode: kFit (fitting) or kView (viewing/plotting)
|
||||
* \param theoAsData If true, theory is calculated only at data points (for viewing);
|
||||
* if false, theory uses finer time grid (8× data resolution)
|
||||
*
|
||||
* \warning Packing MUST be specified either in the RUN block or GLOBAL block.
|
||||
* If packing is not found, the constructor sets fValid=false and returns.
|
||||
*
|
||||
* \note After construction, check IsValid() to ensure initialization succeeded.
|
||||
*
|
||||
* \see PrepareData(), IsScaleN0AndBkg()
|
||||
*/
|
||||
PRunSingleHisto::PRunSingleHisto(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t runNo, EPMusrHandleTag tag, Bool_t theoAsData) :
|
||||
PRunBase(msrInfo, rawData, runNo, tag), fTheoAsData(theoAsData)
|
||||
@@ -119,7 +144,11 @@ PRunSingleHisto::PRunSingleHisto(PMsrHandler *msrInfo, PRunDataHandler *rawData,
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor
|
||||
* \brief Destructor for single histogram fitting class.
|
||||
*
|
||||
* Cleans up dynamically allocated memory:
|
||||
* - Clears the forward histogram data vector
|
||||
* - Base class destructor handles theory objects and other shared resources
|
||||
*/
|
||||
PRunSingleHisto::~PRunSingleHisto()
|
||||
{
|
||||
@@ -130,12 +159,51 @@ PRunSingleHisto::~PRunSingleHisto()
|
||||
// CalcChiSquare (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate chi-square.
|
||||
* \brief Calculates χ² between data and theory (least-squares fit metric).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value
|
||||
* Computes the standard chi-square goodness-of-fit statistic:
|
||||
* \f[
|
||||
* \chi^2 = \sum_{i=t_{\rm start}}^{t_{\rm end}} \frac{[N_i - N_{\rm theo}(t_i)]^2}{\sigma_i^2}
|
||||
* \f]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* where the theory function is:
|
||||
* \f[
|
||||
* N_{\rm theo}(t) = N_0 e^{-t/\tau_\mu} [1 + P(t)] + B
|
||||
* \f]
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Extract N₀ from parameter vector or evaluate as a function
|
||||
* -# Extract muon lifetime τ (defaults to PMUON_LIFETIME if not fitted)
|
||||
* -# Extract background B (from fit parameter, fixed value, or estimated range)
|
||||
* -# Evaluate all user-defined functions in FUNCTIONS block
|
||||
* -# Pre-calculate theory at t=1.0 to initialize LF/user functions (thread-safe)
|
||||
* -# Loop over fit range bins [fStartTimeBin, fEndTimeBin) using OpenMP parallelization
|
||||
* -# Accumulate χ² with reduction across threads
|
||||
* -# Apply correction factor if fScaleN0AndBkg is true
|
||||
*
|
||||
* <b>N₀ Parameter vs. Function Handling:</b>
|
||||
* - If norm parameter number < MSR_PARAM_FUN_OFFSET: N₀ is a fit parameter
|
||||
* - If norm parameter number ≥ MSR_PARAM_FUN_OFFSET: N₀ is a user-defined function
|
||||
*
|
||||
* <b>OpenMP Parallelization:</b>
|
||||
* - Dynamic scheduling with chunk size = (N_bins / N_processors), minimum 10
|
||||
* - Private variables per thread: i, time, diff
|
||||
* - Reduction performed on chisq sum
|
||||
*
|
||||
* <b>Scaling Correction:</b>
|
||||
* If fScaleN0AndBkg is true, χ² is multiplied by:
|
||||
* \f[
|
||||
* \text{correction} = \text{packing} \times (t_{\rm res} \times 1000)
|
||||
* \f]
|
||||
* This accounts for the fact that data scales like pack×t_res, but errors
|
||||
* scale like √(pack×t_res), ensuring correct χ² when normalizing to 1/ns.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT2 optimizer (1-based indexing in MSR file,
|
||||
* but 0-based in this vector)
|
||||
*
|
||||
* \return Chi-square value for the current parameter set
|
||||
*
|
||||
* \see CalcChiSquareExpected(), CalcMaxLikelihood(), PTheory::Func()
|
||||
*/
|
||||
Double_t PRunSingleHisto::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -214,12 +282,43 @@ Double_t PRunSingleHisto::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
// CalcChiSquareExpected (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate expected chi-square.
|
||||
* \brief Calculates expected χ² using theory as variance (alternative fit metric).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value
|
||||
* Computes chi-square using the expected variance (theory value) instead of
|
||||
* observed variance. This is sometimes called the "Neyman χ²" or "expected χ²":
|
||||
* \f[
|
||||
* \chi^2_{\rm exp} = \sum_{i=t_{\rm start}}^{t_{\rm end}} \frac{[N_i - N_{\rm theo}(t_i)]^2}{N_{\rm theo}(t_i)}
|
||||
* \f]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* <b>Difference from Standard χ²:</b>
|
||||
* - Standard χ²: variance = σ²ᵢ (from observed data)
|
||||
* - Expected χ²: variance = N_theo(tᵢ) (from theory prediction)
|
||||
*
|
||||
* This metric can be useful when:
|
||||
* - Theory predictions are more reliable than data errors
|
||||
* - Data contains zero or very low counts (standard χ² undefined)
|
||||
* - Testing model consistency against expected distribution
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Extract N₀ from parameter vector or evaluate as a function
|
||||
* -# Extract muon lifetime τ (defaults to PMUON_LIFETIME if not fitted)
|
||||
* -# Extract background B (from fit parameter, fixed value, or estimated range)
|
||||
* -# Evaluate all user-defined functions in FUNCTIONS block
|
||||
* -# Pre-calculate theory at t=1.0 to initialize LF/user functions (thread-safe)
|
||||
* -# Loop over fit range bins [fStartTimeBin, fEndTimeBin) using OpenMP parallelization
|
||||
* -# Accumulate χ²_exp with reduction across threads
|
||||
* -# Apply correction factor if fScaleN0AndBkg is true
|
||||
*
|
||||
* <b>OpenMP Parallelization:</b>
|
||||
* - Dynamic scheduling with chunk size = (N_bins / N_processors), minimum 10
|
||||
* - Private variables per thread: i, time, theo, diff
|
||||
* - Reduction performed on chisq sum
|
||||
*
|
||||
* \param par Parameter vector from MINUIT2 optimizer
|
||||
*
|
||||
* \return Expected chi-square value for the current parameter set
|
||||
*
|
||||
* \see CalcChiSquare(), CalcMaxLikelihood()
|
||||
*/
|
||||
Double_t PRunSingleHisto::CalcChiSquareExpected(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -299,12 +398,59 @@ Double_t PRunSingleHisto::CalcChiSquareExpected(const std::vector<Double_t>& par
|
||||
// CalcMaxLikelihood (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate log maximum-likelihood. See http://pdg.lbl.gov/index.html
|
||||
* \brief Calculates -2 log(maximum likelihood) for Poisson-distributed histogram data.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - log maximum-likelihood value
|
||||
* Computes the negative log-likelihood assuming Poisson statistics for each bin.
|
||||
* This is the preferred fit metric for low-count data where Gaussian approximations
|
||||
* break down. The likelihood function is:
|
||||
* \f[
|
||||
* -2\ln\mathcal{L} = 2 \sum_{i} \left[ N_{\rm theo}(t_i) - N_i + N_i \ln\frac{N_i}{N_{\rm theo}(t_i)} \right]
|
||||
* \f]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* This is derived from the Poisson probability:
|
||||
* \f[
|
||||
* P(N_i | N_{\rm theo}) = \frac{N_{\rm theo}^{N_i} e^{-N_{\rm theo}}}{N_i!}
|
||||
* \f]
|
||||
*
|
||||
* The factor of 2 makes -2ln(L) asymptotically distributed as χ² for large N,
|
||||
* allowing use of standard error estimation from MINUIT.
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Extract N₀ from parameter vector or evaluate as a function
|
||||
* -# Extract muon lifetime τ (defaults to PMUON_LIFETIME if not fitted)
|
||||
* -# Extract background B (from fit parameter, fixed value, or estimated range)
|
||||
* -# Evaluate all user-defined functions in FUNCTIONS block
|
||||
* -# Pre-calculate theory at t=1.0 to initialize LF/user functions (thread-safe)
|
||||
* -# Calculate normalizer = packing × t_res × 1000 (if fScaleN0AndBkg is true)
|
||||
* -# Loop over fit range bins [fStartTimeBin, fEndTimeBin) using OpenMP parallelization
|
||||
* -# For each bin:
|
||||
* - Calculate theory N_theo(t)
|
||||
* - If N_theo ≤ 0: skip bin with warning (negative theory is unphysical)
|
||||
* - If N_data > 10⁻⁹: add (theo - data) + data×ln(data/theo)
|
||||
* - If N_data ≈ 0: add (theo - data) only (limit as data→0)
|
||||
* -# Accumulate -2ln(L) with reduction across threads
|
||||
* -# Apply normalizer scaling
|
||||
*
|
||||
* <b>Edge Cases:</b>
|
||||
* - <b>Zero data (Nᵢ = 0):</b> Uses limit: -2ln(L) → 2×N_theo
|
||||
* - <b>Negative theory:</b> Skips bin and prints warning (should not occur with valid parameters)
|
||||
* - <b>Data threshold:</b> Uses 10⁻⁹ to distinguish zero from non-zero data
|
||||
*
|
||||
* <b>OpenMP Parallelization:</b>
|
||||
* - Dynamic scheduling with chunk size = (N_bins / N_processors), minimum 10
|
||||
* - Private variables per thread: i, time, theo, data
|
||||
* - Reduction performed on mllh sum (note: reduction(-:mllh) for subtraction)
|
||||
*
|
||||
* <b>When to Use Maximum Likelihood vs. χ²:</b>
|
||||
* - <b>Use likelihood:</b> Low count rates (< 100 counts/bin), asymmetric errors
|
||||
* - <b>Use χ²:</b> High count rates (> 100 counts/bin), Gaussian regime
|
||||
*
|
||||
* \param par Parameter vector from MINUIT2 optimizer
|
||||
*
|
||||
* \return -2 × log(maximum likelihood) for the current parameter set
|
||||
*
|
||||
* \see CalcChiSquare(), CalcMaxLikelihoodExpected()
|
||||
* \see PDG Review of Particle Physics: Statistics section (http://pdg.lbl.gov)
|
||||
*/
|
||||
Double_t PRunSingleHisto::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -397,12 +543,49 @@ Double_t PRunSingleHisto::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
// CalcMaxLikelihoodExpected (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate expected log maximum-likelihood.
|
||||
* \brief Calculates expected -2 log(maximum likelihood) using G-test formulation.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - log maximum-likelihood value
|
||||
* Computes an alternative form of the Poisson likelihood using only the data×ln(data/theo)
|
||||
* term. This is related to the G-test (likelihood ratio test) and represents the
|
||||
* "expected" contribution to the likelihood:
|
||||
* \f[
|
||||
* -2\ln\mathcal{L}_{\rm exp} = 2 \sum_{i} N_i \ln\frac{N_i}{N_{\rm theo}(t_i)}
|
||||
* \f]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* <b>Difference from CalcMaxLikelihood():</b>
|
||||
* - <b>Full likelihood:</b> includes (theo - data) + data×ln(data/theo)
|
||||
* - <b>Expected likelihood:</b> includes only data×ln(data/theo)
|
||||
*
|
||||
* The omitted (theo - data) term represents the "prior" expectation and is
|
||||
* constant for a given theory. This formulation is sometimes used in:
|
||||
* - G-test for goodness-of-fit (likelihood ratio test)
|
||||
* - Comparing relative likelihoods between models
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Extract N₀, τ, and background B (same as CalcMaxLikelihood)
|
||||
* -# Evaluate all user-defined functions in FUNCTIONS block
|
||||
* -# Pre-calculate theory at t=1.0 to initialize LF/user functions (thread-safe)
|
||||
* -# Calculate normalizer = packing × t_res × 1000 (if fScaleN0AndBkg is true)
|
||||
* -# Loop over fit range bins using OpenMP parallelization
|
||||
* -# For each bin with N_data > 10⁻⁹:
|
||||
* - Calculate theory N_theo(t)
|
||||
* - Add data × ln(data/theo) to likelihood sum
|
||||
* -# Skip bins with N_data ≈ 0 (zero contribution to expected likelihood)
|
||||
* -# Apply normalizer × 2.0 scaling
|
||||
*
|
||||
* \warning The comment "is this correct?? needs to be checked. See G-test"
|
||||
* in the code indicates this implementation may need verification.
|
||||
*
|
||||
* <b>OpenMP Parallelization:</b>
|
||||
* - Dynamic scheduling with chunk size = (N_bins / N_processors), minimum 10
|
||||
* - Private variables per thread: i, time, theo, data
|
||||
* - Reduction performed on mllh sum
|
||||
*
|
||||
* \param par Parameter vector from MINUIT2 optimizer
|
||||
*
|
||||
* \return -2 × log(expected likelihood) for the current parameter set
|
||||
*
|
||||
* \see CalcMaxLikelihood(), G-test (likelihood ratio test)
|
||||
*/
|
||||
Double_t PRunSingleHisto::CalcMaxLikelihoodExpected(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -493,7 +676,40 @@ Double_t PRunSingleHisto::CalcMaxLikelihoodExpected(const std::vector<Double_t>&
|
||||
// CalcTheory (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate theory for a given set of fit-parameters.
|
||||
* \brief Calculates theory curve N(t) for the current parameter values.
|
||||
*
|
||||
* Evaluates the single histogram theory function:
|
||||
* \f[
|
||||
* N(t) = N_0 e^{-t/\tau_\mu} [1 + P(t)] + B
|
||||
* \f]
|
||||
*
|
||||
* for all time bins in the data set, storing results in fData.fTheory.
|
||||
* This is used for:
|
||||
* - Displaying fitted theory curves in plots
|
||||
* - Calculating residuals (data - theory)
|
||||
* - Exporting theory predictions
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Extract current parameter values from MSR parameter list
|
||||
* -# Determine N₀ (from parameter or function evaluation)
|
||||
* -# Determine muon lifetime τ (from parameter or default PMUON_LIFETIME)
|
||||
* -# Determine background B (from fit parameter, fixed value, or estimate)
|
||||
* -# Evaluate all user-defined functions in FUNCTIONS block
|
||||
* -# Loop over all data bins (not just fit range):
|
||||
* - Calculate time t for bin i
|
||||
* - Evaluate P(t) = fTheory->Func(t, par, fFuncValues)
|
||||
* - Calculate N(t) and append to theory vector
|
||||
* -# Clean up temporary parameter vector
|
||||
*
|
||||
* <b>Time Grid:</b>
|
||||
* - Start time: fData.GetDataTimeStart()
|
||||
* - Time step: fData.GetDataTimeStep()
|
||||
* - Number of points: fData.GetValue()->size()
|
||||
*
|
||||
* \note Theory is calculated for the entire data range, not just the fit range,
|
||||
* to enable full visualization of the model.
|
||||
*
|
||||
* \see PRunDataHandler::AppendTheoryValue(), PTheory::Func()
|
||||
*/
|
||||
void PRunSingleHisto::CalcTheory()
|
||||
{
|
||||
@@ -557,9 +773,21 @@ void PRunSingleHisto::CalcTheory()
|
||||
// GetNoOfFitBins (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the number of fitted bins for the current fit range.
|
||||
* \brief Returns the number of bins in the current fit range.
|
||||
*
|
||||
* <b>return:</b> number of fitted bins.
|
||||
* Calculates (if not already done) and returns the number of data bins
|
||||
* that will be included in the χ² or likelihood calculation. This is
|
||||
* determined by the fit range [fFitStartTime, fFitEndTime] and the
|
||||
* data time grid.
|
||||
*
|
||||
* The calculation is performed by CalcNoOfFitBins(), which sets:
|
||||
* - fStartTimeBin: first bin index in fit range
|
||||
* - fEndTimeBin: one past last bin index in fit range
|
||||
* - fNoOfFitBins = fEndTimeBin - fStartTimeBin
|
||||
*
|
||||
* \return Number of bins in the fit range (degrees of freedom = N_bins - N_params)
|
||||
*
|
||||
* \see CalcNoOfFitBins(), SetFitRangeBin()
|
||||
*/
|
||||
UInt_t PRunSingleHisto::GetNoOfFitBins()
|
||||
{
|
||||
@@ -572,15 +800,47 @@ UInt_t PRunSingleHisto::GetNoOfFitBins()
|
||||
// SetFitRangeBin (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Allows to change the fit range on the fly. Used in the COMMAND block.
|
||||
* The syntax of the string is: FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]].
|
||||
* If only one pair of fgb/lgb is given, it is used for all runs in the RUN block section.
|
||||
* If multiple fgb/lgb's are given, the number N has to be the number of RUN blocks in
|
||||
* the msr-file.
|
||||
* \brief Dynamically changes the fit range from COMMAND block instructions.
|
||||
*
|
||||
* <p>nXY are offsets which can be used to shift, limit the fit range.
|
||||
* Parses and applies a FIT_RANGE command to modify the fit range on the fly,
|
||||
* typically used during interactive fitting sessions or systematic scans.
|
||||
*
|
||||
* \param fitRange string containing the necessary information.
|
||||
* <b>Syntax (in COMMAND block):</b>
|
||||
* \code
|
||||
* FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
|
||||
* \endcode
|
||||
*
|
||||
* where:
|
||||
* - <b>fgb:</b> First good bin (start of fit range)
|
||||
* - <b>lgb:</b> Last good bin (end of fit range)
|
||||
* - <b>+nXY / -nXY:</b> Optional offsets to shift the range (+ extends, - contracts)
|
||||
* - <b>Multiple pairs:</b> If N+1 pairs given, they apply to each of N RUN blocks
|
||||
*
|
||||
* <b>Two modes:</b>
|
||||
* -# <b>Single pair:</b> `FIT_RANGE fgb lgb` applies to all runs
|
||||
* -# <b>Per-run pairs:</b> `FIT_RANGE fgb₀ lgb₀ fgb₁ lgb₁ ...` applies
|
||||
* pair i to RUN block i
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Tokenize the fitRange string by spaces/tabs
|
||||
* -# If 3 tokens (FIT_RANGE + 2 values): apply to this run
|
||||
* -# If >3 tokens and odd number: extract pair for this run's index (fRunNo)
|
||||
* -# Parse offsets from + or - characters in fgb/lgb strings
|
||||
* -# Calculate new fFitStartTime and fFitEndTime:
|
||||
* - fFitStartTime = (fGoodBins[0] + offset - t0) × t_res
|
||||
* - fFitEndTime = (fGoodBins[1] - offset - t0) × t_res
|
||||
*
|
||||
* <b>Example:</b>
|
||||
* \code
|
||||
* FIT_RANGE 100+10 500-20 # Fit from bin 110 to bin 480 (applying offsets)
|
||||
* \endcode
|
||||
*
|
||||
* \param fitRange String from COMMAND block containing FIT_RANGE specification
|
||||
*
|
||||
* \note Errors in parsing (wrong number of tokens) are reported to std::cerr
|
||||
* and the command is ignored.
|
||||
*
|
||||
* \see CalcNoOfFitBins(), GetProperFitRange()
|
||||
*/
|
||||
void PRunSingleHisto::SetFitRangeBin(const TString fitRange)
|
||||
{
|
||||
@@ -662,7 +922,31 @@ void PRunSingleHisto::SetFitRangeBin(const TString fitRange)
|
||||
// CalcNoOfFitBins (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the number of fitted bins for the current fit range.
|
||||
* \brief Calculates the number of bins in the fit range and caches bin indices.
|
||||
*
|
||||
* Converts the fit time range [fFitStartTime, fFitEndTime] to bin indices
|
||||
* [fStartTimeBin, fEndTimeBin) and computes the total number of fit bins.
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Calculate start bin: \f$ \lceil \frac{t_{\rm start} - t_{\rm data,0}}{\Delta t} \rceil \f$
|
||||
* -# Clamp fStartTimeBin to [0, N_data)
|
||||
* -# Calculate end bin: \f$ \lfloor \frac{t_{\rm end} - t_{\rm data,0}}{\Delta t} \rfloor + 1 \f$
|
||||
* -# Clamp fEndTimeBin to [0, N_data]
|
||||
* -# Compute fNoOfFitBins = fEndTimeBin - fStartTimeBin (or 0 if invalid)
|
||||
*
|
||||
* where:
|
||||
* - t_data,0 = fData.GetDataTimeStart() (time of first data bin)
|
||||
* - Δt = fData.GetDataTimeStep() (time bin width after packing)
|
||||
*
|
||||
* <b>Edge Cases:</b>
|
||||
* - If fStartTimeBin < 0: clamped to 0
|
||||
* - If fEndTimeBin > N_data: clamped to N_data
|
||||
* - If fEndTimeBin ≤ fStartTimeBin: fNoOfFitBins = 0 (invalid range)
|
||||
*
|
||||
* \note This method is called automatically by GetNoOfFitBins() and by
|
||||
* PrepareData() after setting up the data arrays.
|
||||
*
|
||||
* \see GetNoOfFitBins(), SetFitRangeBin()
|
||||
*/
|
||||
void PRunSingleHisto::CalcNoOfFitBins()
|
||||
{
|
||||
@@ -684,17 +968,45 @@ void PRunSingleHisto::CalcNoOfFitBins()
|
||||
// PrepareData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Prepare data for fitting or viewing. What is already processed at this stage:
|
||||
* -# get proper raw run data
|
||||
* -# get all needed forward histograms
|
||||
* -# get time resolution
|
||||
* -# get t0's and perform necessary cross checks (e.g. if t0 of msr-file (if present) are consistent with t0 of the data files, etc.)
|
||||
* -# add runs (if addruns are present)
|
||||
* -# group histograms (if grouping is present)
|
||||
* \brief Main data preprocessing pipeline for single histogram runs.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if everthing went smooth
|
||||
* - false, otherwise.
|
||||
* Orchestrates the complete data loading and preprocessing workflow:
|
||||
* -# <b>Load raw data:</b> Fetch run from PRunDataHandler using run name
|
||||
* -# <b>Extract metadata:</b> Magnetic field, beam energy, temperature(s)
|
||||
* -# <b>Validate histograms:</b> Check that forward histogram numbers exist in data file
|
||||
* -# <b>Get time resolution:</b> Extract bin width (typically 0.1-10 ns)
|
||||
* -# <b>Determine t0:</b> Call GetProperT0() for muon arrival times
|
||||
* -# <b>Load histogram data:</b> Copy forward histogram bins from raw data
|
||||
* -# <b>Add runs (ADDRUN):</b> If multiple runs specified, add them with t0 alignment
|
||||
* -# <b>Group histograms:</b> Sum multiple detectors within a group (with t0 alignment)
|
||||
* -# <b>Get data range (fgb/lgb):</b> Call GetProperDataRange() for good bin limits
|
||||
* -# <b>Get fit range:</b> Call GetProperFitRange() for fit time window
|
||||
* -# <b>Check lifetime correction:</b> Determine if exponential decay should be removed (for viewing)
|
||||
* -# <b>Dispatch to preparation:</b>
|
||||
* - kFit → PrepareFitData(): packing, background subtraction
|
||||
* - kView (no lifetime corr.) → PrepareRawViewData(): packing, theory calculation
|
||||
* - kView (with lifetime corr.) → PrepareViewData(): lifetime removal, theory
|
||||
*
|
||||
* <b>ADDRUN t0 Alignment:</b>
|
||||
* When adding runs, histograms are aligned by their t0 values:
|
||||
* \code
|
||||
* forward[k][j] += addRunData[k]->at(j + addT0[k] - mainT0[k])
|
||||
* \endcode
|
||||
* This ensures muon arrival times coincide across added runs.
|
||||
*
|
||||
* <b>Grouping t0 Alignment:</b>
|
||||
* When grouping histograms, they are aligned to the first histogram's t0:
|
||||
* \code
|
||||
* fForward[j] += forward[i][j + t0[i] - t0[0]]
|
||||
* \endcode
|
||||
*
|
||||
* \return true if all preprocessing steps succeeded, false otherwise
|
||||
*
|
||||
* \note If any step fails (missing data file, invalid histogram numbers, t0 errors),
|
||||
* this method returns false and error messages are printed to std::cerr.
|
||||
*
|
||||
* \see GetProperT0(), GetProperDataRange(), GetProperFitRange(),
|
||||
* PrepareFitData(), PrepareRawViewData(), PrepareViewData()
|
||||
*/
|
||||
Bool_t PRunSingleHisto::PrepareData()
|
||||
{
|
||||
@@ -757,10 +1069,16 @@ Bool_t PRunSingleHisto::PrepareData()
|
||||
forward[i] = *runData->GetDataBin(histoNo[i]);
|
||||
}
|
||||
|
||||
// check if a dead time correction has to be done
|
||||
// this will be done automatically in the function itself, which also
|
||||
// checks in the global and run section
|
||||
DeadTimeCorrection(forward, histoNo);
|
||||
|
||||
// check if there are runs to be added to the current one
|
||||
if (fRunInfo->GetRunNameSize() > 1) { // runs to be added present
|
||||
PRawRunData *addRunData;
|
||||
for (UInt_t i=1; i<fRunInfo->GetRunNameSize(); i++) {
|
||||
std::vector<PDoubleVector> addForward;
|
||||
for (UInt_t i=1; i<fRunInfo->GetRunNameSize(); i++) { // loop over all ADDRUN's
|
||||
|
||||
// get run to be added to the main one
|
||||
addRunData = fRawData->GetRunData(*fRunInfo->GetRunName(i));
|
||||
@@ -770,15 +1088,23 @@ Bool_t PRunSingleHisto::PrepareData()
|
||||
return false;
|
||||
}
|
||||
|
||||
addForward.clear();
|
||||
addForward.resize(histoNo.size()); // resize to number of groups
|
||||
for (UInt_t j=0; j<histoNo.size(); j++) {
|
||||
addForward[j].resize(addRunData->GetDataBin(histoNo[j])->size());
|
||||
addForward[j] = *addRunData->GetDataBin(histoNo[j]);
|
||||
}
|
||||
DeadTimeCorrection(addForward, histoNo);
|
||||
|
||||
// add forward run
|
||||
UInt_t addRunSize;
|
||||
for (UInt_t k=0; k<histoNo.size(); k++) { // fill each group
|
||||
addRunSize = addRunData->GetDataBin(histoNo[k])->size();
|
||||
for (UInt_t j=0; j<addRunData->GetDataBin(histoNo[k])->size(); j++) { // loop over the bin indices
|
||||
addRunSize = addForward[k].size();
|
||||
for (UInt_t j=0; j<addRunSize; j++) { // loop over the bin indices
|
||||
// make sure that the index stays in the proper range
|
||||
if ((static_cast<Int_t>(j)+static_cast<Int_t>(fAddT0s[i-1][k])-static_cast<Int_t>(fT0s[k]) >= 0) &&
|
||||
(j+static_cast<Int_t>(fAddT0s[i-1][k])-static_cast<Int_t>(fT0s[k]) < addRunSize)) {
|
||||
forward[k][j] += addRunData->GetDataBin(histoNo[k])->at(j+static_cast<Int_t>(fAddT0s[i-1][k])-static_cast<Int_t>(fT0s[k]));
|
||||
forward[k][j] += addForward[k][j+static_cast<Int_t>(fAddT0s[i-1][k])-static_cast<Int_t>(fT0s[k])];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -834,19 +1160,55 @@ Bool_t PRunSingleHisto::PrepareData()
|
||||
// PrepareFitData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Take the pre-processed data (i.e. grouping and addrun are preformed) and form the histogram for fitting.
|
||||
* The following steps are preformed:
|
||||
* -# get fit start/stop time
|
||||
* -# check that 'first good data bin', 'last good data bin', and 't0' make any sense
|
||||
* -# check how the background shall be handled, i.e. fitted, subtracted from background estimate data range, or subtacted from a given fixed background.
|
||||
* -# packing (i.e rebinning)
|
||||
* \brief Prepares histogram data for fitting (kFit mode).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true, if everything went smooth
|
||||
* - false, otherwise
|
||||
* Performs final data transformations after PrepareData() has loaded and grouped
|
||||
* the raw histogram data:
|
||||
* -# <b>Estimate N₀ (optional):</b> If MSR file requests it, call EstimateN0()
|
||||
* -# <b>Handle background:</b>
|
||||
* - If background is fitted: leave data unchanged
|
||||
* - If fixed background given: subtract it from all bins
|
||||
* - If background range given: call EstimateBkg() and subtract estimate
|
||||
* - If nothing specified: auto-estimate from bins [0.1×t0, 0.6×t0] with warning
|
||||
* -# <b>Packing (rebinning):</b> Combine consecutive bins to improve statistics:
|
||||
* - If packing = 1: copy bins directly
|
||||
* - If packing > 1: sum every 'packing' bins into one
|
||||
* -# <b>Normalization:</b> If fScaleN0AndBkg is true, divide by (packing × t_res × 1000)
|
||||
* to normalize counts to 1/ns
|
||||
* -# <b>Error calculation:</b>
|
||||
* - If N > 0: σ = √N (Poisson statistics)
|
||||
* - If N = 0: σ = 1/normalizer (avoid division by zero in χ²)
|
||||
* -# <b>Set time grid:</b>
|
||||
* - Data start time: (fgb - 0.5 + pack/2 - t0) × t_res
|
||||
* - Data time step: pack × t_res
|
||||
* -# <b>Calculate fit bins:</b> Call CalcNoOfFitBins() to set fStartTimeBin, fEndTimeBin
|
||||
*
|
||||
* \param runData raw run data handler
|
||||
* \param histoNo forward histogram number
|
||||
* <b>Packing Algorithm:</b>
|
||||
* \code
|
||||
* for (i = fgb; i < lgb; i++) {
|
||||
* value += forward[i];
|
||||
* if ((i-fgb) % packing == 0 && i != fgb) {
|
||||
* data.push_back(value / normalizer);
|
||||
* error.push_back(sqrt(value) / normalizer);
|
||||
* value = 0;
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* <b>Background Handling Priority:</b>
|
||||
* -# Check if background is fitted (bkgFitParamNo ≠ -1) → leave data as-is
|
||||
* -# Check if fixed background given (bkgFix ≠ PMUSR_UNDEFINED) → subtract fixed value
|
||||
* -# Check if background range given (bkgRange[0] ≥ 0) → estimate and subtract
|
||||
* -# Fallback: auto-estimate from [0.1×t0, 0.6×t0] → print warning
|
||||
*
|
||||
* \param runData Pointer to raw run data handler (for metadata access)
|
||||
* \param histoNo Forward histogram number (for background estimation)
|
||||
*
|
||||
* \return true if preparation succeeded, false if EstimateBkg() failed
|
||||
*
|
||||
* \note This method populates fData (PRunData object) with packed data ready for fitting.
|
||||
*
|
||||
* \see PrepareData(), EstimateBkg(), EstimateN0(), CalcNoOfFitBins()
|
||||
*/
|
||||
Bool_t PRunSingleHisto::PrepareFitData(PRawRunData* runData, const UInt_t histoNo)
|
||||
{
|
||||
@@ -1383,21 +1745,54 @@ Bool_t PRunSingleHisto::PrepareViewData(PRawRunData* runData, const UInt_t histo
|
||||
// GetProperT0 (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the proper t0 for the single histogram run.
|
||||
* -# the t0 vector size = number of detectors (grouping) for forward.
|
||||
* -# initialize t0's with -1
|
||||
* -# fill t0's from RUN block
|
||||
* -# if t0's are missing (i.e. t0 == -1), try to fill from the GLOBAL block.
|
||||
* -# if t0's are missing, try t0's from the data file
|
||||
* -# if t0's are missing, try to estimate them
|
||||
* \brief Determines time-zero (t0) values for all histograms using hierarchical fallback.
|
||||
*
|
||||
* \param runData pointer to the current RUN block entry from the msr-file
|
||||
* \param globalBlock pointer to the GLOBLA block entry from the msr-file
|
||||
* \param histoNo histogram number vector of forward; histoNo = msr-file forward + redGreen_offset - 1
|
||||
* Time-zero (t0) marks the muon arrival time in each detector histogram, the reference
|
||||
* point from which decay time is measured. This method uses a priority system to find
|
||||
* t0 values:
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if everthing went smooth
|
||||
* - false, otherwise.
|
||||
* <b>Priority hierarchy (highest to lowest):</b>
|
||||
* -# <b>RUN block t0:</b> Explicitly specified in the RUN block (highest priority)
|
||||
* -# <b>GLOBAL block t0:</b> Default t0 for all runs in the GLOBAL block
|
||||
* -# <b>Data file t0:</b> Stored in the raw data file (from previous analysis)
|
||||
* -# <b>Estimated t0:</b> Automatic estimation (UNRELIABLE, prints warning)
|
||||
*
|
||||
* <b>For ADDRUN support:</b>
|
||||
* If multiple runs are added (fRunInfo->GetRunNameSize() > 1), this method also
|
||||
* determines t0 values for each added run (fAddT0s) using the same hierarchy.
|
||||
* Proper t0 alignment is essential for correct ADDRUN operation.
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Resize fT0s vector to histogram count (number of grouped detectors)
|
||||
* -# Initialize all t0 values to -1.0 (sentinel for "not set")
|
||||
* -# Fill from RUN block (if specified)
|
||||
* -# Fill from GLOBAL block where still -1.0
|
||||
* -# Fill from data file where still -1.0
|
||||
* -# Fill from estimation where still -1.0 (prints **WARNING**)
|
||||
* -# Validate all t0 values are within histogram bounds
|
||||
* -# If ADDRUN present: repeat steps 2-6 for each added run
|
||||
*
|
||||
* <b>Validation:</b>
|
||||
* After fallback, checks that each t0 satisfies:
|
||||
* \f[
|
||||
* 0 \leq t_0 \leq N_{\rm bins}
|
||||
* \f]
|
||||
* If validation fails, returns false with error message.
|
||||
*
|
||||
* \param runData Pointer to raw run data handler for main run
|
||||
* \param globalBlock Pointer to GLOBAL block from MSR file
|
||||
* \param histoNo Vector of histogram indices (zero-based, after redGreen offset correction)
|
||||
*
|
||||
* \return true if all t0 values found and validated, false if any t0 is out of bounds
|
||||
*
|
||||
* \warning Estimated t0 values (fallback option #4) are often UNRELIABLE, especially
|
||||
* for low-energy muons (LEM). Manual specification in MSR file is strongly
|
||||
* recommended. A warning is printed to std::cerr when estimation is used.
|
||||
*
|
||||
* \note This method updates fT0s (main run) and fAddT0s (ADDRUN) member variables.
|
||||
* It also updates the MSR file handler with found t0 values for persistence.
|
||||
*
|
||||
* \see PrepareData(), fT0s, fAddT0s
|
||||
*/
|
||||
Bool_t PRunSingleHisto::GetProperT0(PRawRunData* runData, PMsrGlobalBlock *globalBlock, PUIntVector &histoNo)
|
||||
{
|
||||
@@ -1521,14 +1916,48 @@ Bool_t PRunSingleHisto::GetProperT0(PRawRunData* runData, PMsrGlobalBlock *globa
|
||||
// GetProperDataRange (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the proper data range, i.e. first/last good bin (fgb/lgb).
|
||||
* -# get fgb/lgb from the RUN block
|
||||
* -# if fgb/lgb still undefined, try to get it from the GLOBAL block
|
||||
* -# if fgb/lgb still undefined, try to estimate them.
|
||||
* \brief Determines the data range (first good bin / last good bin).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if everthing went smooth
|
||||
* - false, otherwise.
|
||||
* Establishes which histogram bins contain valid muon decay data by
|
||||
* finding the "first good bin" (fgb) and "last good bin" (lgb). This
|
||||
* range excludes:
|
||||
* - Pre-t0 bins (before muon arrival)
|
||||
* - Early bins affected by detector dead time or pileup
|
||||
* - Late bins with insufficient statistics
|
||||
*
|
||||
* <b>Priority hierarchy (highest to lowest):</b>
|
||||
* -# <b>RUN block:</b> Explicitly specified fgb/lgb in RUN block
|
||||
* -# <b>GLOBAL block:</b> Default fgb/lgb from GLOBAL block
|
||||
* -# <b>Auto-estimation:</b> Fallback estimates with warning
|
||||
*
|
||||
* <b>Auto-estimation (if not specified):</b>
|
||||
* - <b>fgb:</b> t0 + 10 ns (to avoid dead time issues)
|
||||
* - <b>lgb:</b> End of histogram (all bins)
|
||||
*
|
||||
* <b>Validation:</b>
|
||||
* -# Check fgb < lgb (swap if necessary)
|
||||
* -# Check 0 ≤ fgb < histogram length
|
||||
* -# Check 0 ≤ lgb ≤ histogram length
|
||||
* -# If lgb > histogram length: clamp to (length - 1) and print warning
|
||||
*
|
||||
* <b>Storage:</b>
|
||||
* Results are stored in:
|
||||
* - fGoodBins[0] = fgb (first good bin index)
|
||||
* - fGoodBins[1] = lgb (last good bin index)
|
||||
*
|
||||
* These values are used by:
|
||||
* - PrepareFitData() to determine packing range
|
||||
* - GetProperFitRange() as fallback for fit range
|
||||
*
|
||||
* \return true if data range is valid and within bounds, false if validation fails
|
||||
*
|
||||
* \warning Auto-estimated ranges may not be appropriate for all detectors.
|
||||
* Explicit specification in MSR file is strongly recommended.
|
||||
*
|
||||
* \note This method is called by PrepareData() after histogram grouping
|
||||
* but before packing and fit range determination.
|
||||
*
|
||||
* \see PrepareData(), GetProperFitRange(), fGoodBins
|
||||
*/
|
||||
Bool_t PRunSingleHisto::GetProperDataRange()
|
||||
{
|
||||
@@ -1609,16 +2038,60 @@ Bool_t PRunSingleHisto::GetProperDataRange()
|
||||
// GetProperFitRange (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the proper fit range. There are two possible fit range commands:
|
||||
* fit <start> <end> given in (usec), or
|
||||
* fit fgb+offset_0 lgb-offset_1 given in (bins), therefore it works the following way:
|
||||
* -# get fit range assuming given in time from RUN block
|
||||
* -# if fit range in RUN block is given in bins, replace start/end
|
||||
* -# if fit range is NOT given yet, try fit range assuming given in time from GLOBAL block
|
||||
* -# if fit range in GLOBAL block is given in bins, replace start/end
|
||||
* -# if still no fit range is given, use fgb/lgb.
|
||||
* \brief Determines the fit range (start and end times for χ² calculation).
|
||||
*
|
||||
* \param globalBlock pointer to the GLOBAL block information form the msr-file.
|
||||
* Establishes the time window [t_start, t_end] over which the fit will be
|
||||
* performed. The fit range can be specified in two ways:
|
||||
*
|
||||
* <b>Specification methods:</b>
|
||||
* -# <b>Time-based:</b> `fit <start> <end>` in microseconds
|
||||
* - Example: `fit 0.1 10.0` (fit from 0.1 to 10.0 μs after t0)
|
||||
* -# <b>Bin-based:</b> `fit fgb[+offset0] lgb[-offset1]` in bins
|
||||
* - Example: `fit fgb+10 lgb-20` (fit from 10 bins after fgb to 20 bins before lgb)
|
||||
*
|
||||
* <b>Priority hierarchy (highest to lowest):</b>
|
||||
* -# <b>RUN block time-based:</b> `fit <start> <end>` in RUN block
|
||||
* -# <b>RUN block bin-based:</b> `fit fgb+n0 lgb-n1` in RUN block
|
||||
* -# <b>GLOBAL block time-based:</b> `fit <start> <end>` in GLOBAL block
|
||||
* -# <b>GLOBAL block bin-based:</b> `fit fgb+n0 lgb-n1` in GLOBAL block
|
||||
* -# <b>Auto-fallback:</b> Use entire data range [fgb, lgb]
|
||||
*
|
||||
* <b>Bin-based conversion to time:</b>
|
||||
* When fit range is given in bins, it's converted to time:
|
||||
* \f[
|
||||
* t_{\rm start} = (\text{fgb} + n_0 - t_0) \times \Delta t
|
||||
* \f]
|
||||
* \f[
|
||||
* t_{\rm end} = (\text{lgb} - n_1 - t_0) \times \Delta t
|
||||
* \f]
|
||||
*
|
||||
* where:
|
||||
* - fgb/lgb = first/last good bin from GetProperDataRange()
|
||||
* - n₀/n₁ = offsets (can be positive or negative)
|
||||
* - t₀ = time-zero bin
|
||||
* - Δt = time resolution (fTimeResolution in μs)
|
||||
*
|
||||
* <b>Storage and updates:</b>
|
||||
* - fFitStartTime, fFitEndTime are set to the determined range
|
||||
* - If bin-based, the converted time values are written back to the MSR
|
||||
* data structure for log file reporting
|
||||
*
|
||||
* <b>Fallback behavior:</b>
|
||||
* If no fit range is specified anywhere, uses the entire data range:
|
||||
* \f[
|
||||
* t_{\rm start} = (\text{fgb} - t_0) \times \Delta t
|
||||
* \f]
|
||||
* \f[
|
||||
* t_{\rm end} = (\text{lgb} - t_0) \times \Delta t
|
||||
* \f]
|
||||
* and prints a warning to std::cerr.
|
||||
*
|
||||
* \param globalBlock Pointer to GLOBAL block from MSR file
|
||||
*
|
||||
* \note This method is called by PrepareData() after GetProperDataRange()
|
||||
* has established fGoodBins[0] and fGoodBins[1].
|
||||
*
|
||||
* \see PrepareData(), GetProperDataRange(), SetFitRangeBin(), CalcNoOfFitBins()
|
||||
*/
|
||||
void PRunSingleHisto::GetProperFitRange(PMsrGlobalBlock *globalBlock)
|
||||
{
|
||||
@@ -1657,7 +2130,46 @@ void PRunSingleHisto::GetProperFitRange(PMsrGlobalBlock *globalBlock)
|
||||
// EstimateN0 (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Estimate the N0 for the given run.
|
||||
* \brief Automatically estimates the normalization parameter N₀ from data.
|
||||
*
|
||||
* Provides an intelligent initial guess for N₀ to help MINUIT convergence.
|
||||
* The estimate is based on the maximum count rate in the fit range, accounting
|
||||
* for muon decay and background.
|
||||
*
|
||||
* <b>When estimation is performed:</b>
|
||||
* - MSR file requests estimation (estimate_n0 flag in GLOBAL block)
|
||||
* - Norm parameter is a fit parameter (not fixed, not a function)
|
||||
* - Parameter step size ≠ 0 (i.e., not fixed)
|
||||
*
|
||||
* <b>When estimation is skipped:</b>
|
||||
* - Norm is a function (paramNo > MSR_PARAM_FUN_OFFSET)
|
||||
* - Norm parameter is fixed (step = 0)
|
||||
* - Invalid parameter number
|
||||
*
|
||||
* <b>Estimation algorithm:</b>
|
||||
* -# Find maximum value in fit range: max_data = max(N(t) in fit range)
|
||||
* -# Find corresponding time t_max
|
||||
* -# Extract or estimate background B
|
||||
* -# Correct for exponential decay: N₀_est = (max_data - B) / exp(-t_max/τ_μ)
|
||||
* -# Adjust for scaling if fScaleN0AndBkg is true
|
||||
* -# Update parameter value and step size in MSR parameter list
|
||||
*
|
||||
* <b>Background handling:</b>
|
||||
* - If background is fitted: extract current background parameter value
|
||||
* - If fixed background given: use fixed value
|
||||
* - If background range given: use fBackground estimate
|
||||
* - Otherwise: assume B = 0
|
||||
*
|
||||
* <b>Scaling adjustment:</b>
|
||||
* If fScaleN0AndBkg is true (normalizing to 1/ns), the estimate is divided by:
|
||||
* \f[
|
||||
* \text{scale factor} = \text{packing} \times (t_{\rm res} \times 1000)
|
||||
* \f]
|
||||
*
|
||||
* \note This method modifies the MSR parameter list in place, updating both
|
||||
* the parameter value and the step size (for MINUIT error estimation).
|
||||
*
|
||||
* \see IsScaleN0AndBkg(), EstimateBkg(), PrepareFitData()
|
||||
*/
|
||||
void PRunSingleHisto::EstimateN0()
|
||||
{
|
||||
@@ -1745,16 +2257,55 @@ void PRunSingleHisto::EstimateN0()
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// EstimatBkg (private)
|
||||
// EstimateBkg (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Estimate the background for a given interval.
|
||||
* \brief Estimates background count rate from pre-t0 bins.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true, if everything went smooth
|
||||
* - false, otherwise
|
||||
* Calculates the average background rate from bins before the muon pulse
|
||||
* arrives. For pulsed beam facilities (PSI, RAL, TRIUMF), adjusts the
|
||||
* background interval to be a multiple of the beam period to avoid
|
||||
* systematic biases from beam structure.
|
||||
*
|
||||
* \param histoNo forward histogram number of the run
|
||||
* <b>Algorithm:</b>
|
||||
* -# Extract background range [start, end] from MSR file (in bins)
|
||||
* -# Validate start < end (swap if necessary)
|
||||
* -# If pulsed beam (PSI/RAL/TRIUMF):
|
||||
* - Calculate interval duration in time: t_bkg = (end - start) × t_res × packing
|
||||
* - Find number of complete beam cycles: N_cycles = floor(t_bkg / T_beam)
|
||||
* - Adjust end bin to match N_cycles × T_beam exactly
|
||||
* -# Validate start and end are within histogram bounds
|
||||
* -# Sum counts in [start, end]: Σ fForward[i]
|
||||
* -# Calculate average: fBackground = Σ counts / (end - start)
|
||||
*
|
||||
* <b>Beam periods:</b>
|
||||
* - <b>PSI:</b> 19.75 ns (50.63 MHz cyclotron)
|
||||
* - <b>RAL (ISIS):</b> 320 ns (3.125 MHz target)
|
||||
* - <b>TRIUMF:</b> 43.0 ns (23.26 MHz cyclotron)
|
||||
* - <b>Other facilities:</b> No period correction applied
|
||||
*
|
||||
* <b>Why adjust to beam period?</b>
|
||||
* Pulsed beams have time-dependent backgrounds from:
|
||||
* - Flash (instantaneous background from beam pulse)
|
||||
* - Prompt particles
|
||||
* - Pion background
|
||||
*
|
||||
* Averaging over complete beam cycles ensures unbiased background estimates
|
||||
* by including all phases of the pulsed structure.
|
||||
*
|
||||
* <b>Edge cases:</b>
|
||||
* - If interval < 1 beam period: uses original end bin (no correction)
|
||||
* - If start ≥ histogram length: returns false with error
|
||||
* - If end ≥ histogram length: returns false with error
|
||||
*
|
||||
* \param histoNo Forward histogram number (for error messages, currently not directly used)
|
||||
*
|
||||
* \return true if background estimated successfully, false if bins out of bounds
|
||||
*
|
||||
* \note The estimated background is stored in fBackground member variable
|
||||
* and subtracted from data in PrepareFitData() if not fitted.
|
||||
*
|
||||
* \see PrepareFitData(), ACCEL_PERIOD_PSI, ACCEL_PERIOD_RAL, ACCEL_PERIOD_TRIUMF
|
||||
*/
|
||||
Bool_t PRunSingleHisto::EstimateBkg(UInt_t histoNo)
|
||||
{
|
||||
@@ -1831,14 +2382,46 @@ Bool_t PRunSingleHisto::EstimateBkg(UInt_t histoNo)
|
||||
// IsScaleN0AndBkg (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Checks if N0/Bkg normalization to 1/ns is whished. The default is yes, since most of the users want to have it that way.
|
||||
* To overwrite this, one should add the line 'SCALE_N0_BKG FALSE' to the command block of the msr-file.
|
||||
* \brief Determines if N₀ and background should be normalized to 1/ns.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true, if scaling of N0 and Bkg to 1/ns is whished
|
||||
* - false, otherwise
|
||||
* Checks whether N₀ and background parameters should be scaled to represent
|
||||
* count rates per nanosecond (1/ns) rather than counts per packed bin.
|
||||
*
|
||||
* \param histoNo forward histogram number of the run
|
||||
* <b>Default behavior:</b> Scaling is ENABLED (true)
|
||||
*
|
||||
* This makes fitted parameters physically meaningful and independent of packing:
|
||||
* - N₀ represents the initial muon decay rate at t=0 in counts/ns
|
||||
* - Background B represents constant background rate in counts/ns
|
||||
*
|
||||
* <b>To disable scaling:</b> Add to MSR file COMMAND block:
|
||||
* \code
|
||||
* SCALE_N0_BKG FALSE
|
||||
* \endcode
|
||||
*
|
||||
* <b>When to disable scaling:</b>
|
||||
* - When N₀ and B should represent total counts per packed bin
|
||||
* - When comparing with older analysis that didn't use scaling
|
||||
* - When packing is 1 (no difference between modes)
|
||||
*
|
||||
* <b>Effect on fit parameters:</b>
|
||||
* - <b>Scaled (default):</b> N₀ and B independent of packing choice
|
||||
* - <b>Unscaled:</b> N₀ and B depend on packing value
|
||||
*
|
||||
* <b>Implementation details:</b>
|
||||
* Scaling is applied in:
|
||||
* - PrepareFitData(): Data is divided by (packing × t_res × 1000)
|
||||
* - CalcChiSquare(): χ² is multiplied by (packing × t_res × 1000)
|
||||
* - CalcMaxLikelihood(): -2ln(L) is multiplied by normalizer
|
||||
* - EstimateBkg(): Background estimate is divided by (t_res × 1000)
|
||||
*
|
||||
* These operations cancel out mathematically but keep parameters in 1/ns units.
|
||||
*
|
||||
* \return true if N₀ and background should be scaled to 1/ns (default),
|
||||
* false if they should represent counts per packed bin
|
||||
*
|
||||
* \note This method is called during construction to set fScaleN0AndBkg.
|
||||
*
|
||||
* \see CalcChiSquare(), CalcMaxLikelihood(), PrepareFitData(), EstimateBkg()
|
||||
*/
|
||||
Bool_t PRunSingleHisto::IsScaleN0AndBkg()
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -53,7 +53,22 @@
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Default constructor for RRF single histogram fitting class.
|
||||
*
|
||||
* Initializes all member variables to safe default values:
|
||||
* - fNoOfFitBins = 0 (no bins to fit)
|
||||
* - fBackground = 0 (will be estimated or set from MSR file)
|
||||
* - fBkgErr = 1.0 (default error estimate)
|
||||
* - fRRFPacking = -1 (invalid until set from GLOBAL block)
|
||||
* - fTheoAsData = false (high-resolution theory grid)
|
||||
* - fGoodBins[0,1] = -1 (calculated from data range)
|
||||
* - fN0EstimateEndTime = 1.0 μs (default N₀ estimation window)
|
||||
*
|
||||
* \warning This constructor creates an invalid object that cannot be used
|
||||
* until properly initialized with MSR file data. Use the full
|
||||
* constructor for normal operation.
|
||||
*
|
||||
* \see PRunSingleHistoRRF(PMsrHandler*, PRunDataHandler*, UInt_t, EPMusrHandleTag, Bool_t)
|
||||
*/
|
||||
PRunSingleHistoRRF::PRunSingleHistoRRF() : PRunBase()
|
||||
{
|
||||
@@ -75,12 +90,44 @@ PRunSingleHistoRRF::PRunSingleHistoRRF() : PRunBase()
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Main constructor for RRF single histogram fitting and viewing.
|
||||
*
|
||||
* \param msrInfo pointer to the msr-file handler
|
||||
* \param rawData raw run data
|
||||
* \param runNo number of the run within the msr-file
|
||||
* \param tag tag showing what shall be done: kFit == fitting, kView == viewing
|
||||
* Constructs a fully initialized RRF single histogram run object by:
|
||||
* -# Validating GLOBAL block presence (mandatory for RRF analysis)
|
||||
* -# Validating RRF frequency specification (rrf_freq in GLOBAL block)
|
||||
* -# Validating RRF packing specification (rrf_packing in GLOBAL block)
|
||||
* -# Calling PrepareData() to load histogram and perform RRF transformation
|
||||
*
|
||||
* <b>GLOBAL Block Requirements:</b>
|
||||
* The RRF fit type requires the following entries in the GLOBAL block:
|
||||
* - \c rrf_freq: Rotation frequency with unit (e.g., "13.554 T", "183.7 MHz")
|
||||
* - \c rrf_packing: Number of bins to average (integer)
|
||||
* - \c rrf_phase: (optional) Initial phase in degrees
|
||||
*
|
||||
* <b>Error Handling:</b>
|
||||
* If any validation fails, the constructor:
|
||||
* - Outputs detailed error message to stderr
|
||||
* - Sets fValid = false
|
||||
* - Returns immediately (PrepareData() is not called)
|
||||
*
|
||||
* \param msrInfo Pointer to MSR file handler (NOT owned, must outlive this object)
|
||||
* \param rawData Pointer to raw run data handler (NOT owned, must outlive this object)
|
||||
* \param runNo Zero-based index of the RUN block in the MSR file
|
||||
* \param tag Operation mode: kFit (fitting) or kView (viewing/plotting)
|
||||
* \param theoAsData If true, theory calculated only at data points (for viewing);
|
||||
* if false, theory uses finer time grid (8× data resolution)
|
||||
*
|
||||
* \warning GLOBAL block with RRF parameters is MANDATORY for this fit type.
|
||||
* Always check IsValid() after construction.
|
||||
*
|
||||
* \note After construction, check IsValid() to ensure initialization succeeded.
|
||||
* Common failure modes:
|
||||
* - Missing GLOBAL block
|
||||
* - Missing rrf_freq specification
|
||||
* - Missing rrf_packing specification
|
||||
* - Data file not found or histogram missing
|
||||
*
|
||||
* \see PrepareData(), PrepareFitData(), PrepareViewData()
|
||||
*/
|
||||
PRunSingleHistoRRF::PRunSingleHistoRRF(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t runNo, EPMusrHandleTag tag, Bool_t theoAsData) :
|
||||
PRunBase(msrInfo, rawData, runNo, tag), fTheoAsData(theoAsData)
|
||||
@@ -131,7 +178,17 @@ PRunSingleHistoRRF::PRunSingleHistoRRF(PMsrHandler *msrInfo, PRunDataHandler *ra
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor
|
||||
* \brief Destructor for RRF single histogram fitting class.
|
||||
*
|
||||
* Cleans up dynamically allocated memory:
|
||||
* - Clears the forward histogram data vector (fForward)
|
||||
* - Other vectors (fM, fMerr, fW, fAerr) are local to PrepareFitData
|
||||
* and cleared automatically
|
||||
*
|
||||
* Base class destructor (PRunBase) handles cleanup of:
|
||||
* - Theory objects
|
||||
* - Function value arrays
|
||||
* - Other shared resources
|
||||
*/
|
||||
PRunSingleHistoRRF::~PRunSingleHistoRRF()
|
||||
{
|
||||
@@ -142,12 +199,42 @@ PRunSingleHistoRRF::~PRunSingleHistoRRF()
|
||||
// CalcChiSquare (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate chi-square.
|
||||
* \brief Calculates χ² between RRF-transformed data and theory (least-squares fit metric).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value
|
||||
* Computes the standard chi-square goodness-of-fit statistic for RRF asymmetry:
|
||||
* \f[
|
||||
* \chi^2 = \sum_{i=t_{\rm start}}^{t_{\rm end}} \frac{[A_{\rm RRF}^{\rm data}(t_i) - A_{\rm RRF}^{\rm theory}(t_i)]^2}{\sigma_i^2}
|
||||
* \f]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* Unlike standard single histogram fitting, no explicit N₀ or exponential decay
|
||||
* factors appear since the RRF transformation already produces dimensionless
|
||||
* asymmetry with properly propagated errors.
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Evaluate all user-defined functions from FUNCTIONS block
|
||||
* -# Pre-evaluate theory at t=1.0 to initialize any stateful functions
|
||||
* (e.g., LF relaxation, user functions with internal state)
|
||||
* -# Loop over fit range bins [fStartTimeBin, fEndTimeBin)
|
||||
* -# For each bin: calculate time, evaluate theory, accumulate χ²
|
||||
*
|
||||
* <b>OpenMP Parallelization:</b>
|
||||
* When compiled with OpenMP (HAVE_GOMP defined):
|
||||
* - Dynamic scheduling with chunk size = max(10, N_bins / N_processors)
|
||||
* - Private variables per thread: i, time, diff
|
||||
* - Reduction performed on chisq accumulator
|
||||
* - Thread-safe due to pre-evaluation of theory at t=1.0
|
||||
*
|
||||
* \param par Parameter vector from MINUIT minimizer, containing current
|
||||
* estimates of all fit parameters
|
||||
*
|
||||
* \return χ² value (sum over all bins in fit range). Minimize this value
|
||||
* during fitting to find optimal parameters.
|
||||
*
|
||||
* \note The theory function is evaluated in the RRF frame. The THEORY block
|
||||
* should describe the low-frequency RRF signal, not the laboratory frame
|
||||
* precession.
|
||||
*
|
||||
* \see CalcChiSquareExpected(), CalcMaxLikelihood()
|
||||
*/
|
||||
Double_t PRunSingleHistoRRF::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -189,12 +276,32 @@ Double_t PRunSingleHistoRRF::CalcChiSquare(const std::vector<Double_t>& par)
|
||||
// CalcChiSquareExpected (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate expected chi-square.
|
||||
* \brief Calculates expected χ² using theory variance instead of data variance.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - chisq value
|
||||
* Computes the expected chi-square where the error estimate in the denominator
|
||||
* comes from the theory prediction rather than the data:
|
||||
* \f[
|
||||
* \chi^2_{\rm exp} = \sum_{i=t_{\rm start}}^{t_{\rm end}} \frac{[A_{\rm RRF}^{\rm data}(t_i) - A_{\rm RRF}^{\rm theory}(t_i)]^2}{A_{\rm RRF}^{\rm theory}(t_i)}
|
||||
* \f]
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* This metric is useful for:
|
||||
* - Diagnostic purposes to assess fit quality
|
||||
* - Detecting systematic deviations from the model
|
||||
* - Comparing with standard χ² to identify error estimation issues
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* Same as CalcChiSquare() but uses theory value as variance estimate instead
|
||||
* of measured error bars. OpenMP parallelization is applied when available.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT minimizer
|
||||
*
|
||||
* \return Expected χ² value. For a good fit, this should be approximately
|
||||
* equal to the number of degrees of freedom (N_bins - N_params).
|
||||
*
|
||||
* \warning Theory values must be positive for valid variance estimate.
|
||||
* Negative theory values can lead to incorrect χ² calculation.
|
||||
*
|
||||
* \see CalcChiSquare()
|
||||
*/
|
||||
Double_t PRunSingleHistoRRF::CalcChiSquareExpected(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -238,12 +345,35 @@ Double_t PRunSingleHistoRRF::CalcChiSquareExpected(const std::vector<Double_t>&
|
||||
// CalcMaxLikelihood (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate log maximum-likelihood. See http://pdg.lbl.gov/index.html
|
||||
* \brief Calculates maximum likelihood for RRF data (NOT YET IMPLEMENTED).
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - log maximum-likelihood value
|
||||
* Maximum likelihood estimation for RRF single histogram data is more complex
|
||||
* than for raw histograms due to the non-linear transformation from
|
||||
* Poisson-distributed counts to RRF asymmetry.
|
||||
*
|
||||
* \param par parameter vector iterated by minuit2
|
||||
* <b>Theoretical Background:</b>
|
||||
* For raw histogram data, the likelihood is:
|
||||
* \f[
|
||||
* \mathcal{L} = \prod_i \frac{\mu_i^{n_i} e^{-\mu_i}}{n_i!}
|
||||
* \f]
|
||||
* where \f$\mu_i\f$ is the expected count and \f$n_i\f$ is the observed count.
|
||||
*
|
||||
* For RRF-transformed data, the error propagation through the transformation
|
||||
* must be properly accounted for in the likelihood function.
|
||||
*
|
||||
* <b>Current Implementation:</b>
|
||||
* Returns 0.0 (not implemented). Use χ² minimization (CalcChiSquare) instead.
|
||||
*
|
||||
* \param par Parameter vector from MINUIT minimizer (unused)
|
||||
*
|
||||
* \return 0.0 (not implemented)
|
||||
*
|
||||
* \todo Implement proper maximum likelihood for RRF data by:
|
||||
* -# Deriving the likelihood function for transformed asymmetry
|
||||
* -# Accounting for error propagation through RRF transformation
|
||||
* -# Including correlations introduced by packing
|
||||
*
|
||||
* \see CalcChiSquare() for currently supported fit metric
|
||||
*/
|
||||
Double_t PRunSingleHistoRRF::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
{
|
||||
@@ -256,7 +386,39 @@ Double_t PRunSingleHistoRRF::CalcMaxLikelihood(const std::vector<Double_t>& par)
|
||||
// CalcTheory (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate theory for a given set of fit-parameters.
|
||||
* \brief Evaluates theory function at all data points for viewing/plotting.
|
||||
*
|
||||
* Calculates the theoretical RRF asymmetry using the current MSR parameter
|
||||
* values and stores results in fData for display. This method is called
|
||||
* after fitting to generate the theory curve overlay.
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Extract parameter values from MSR parameter list
|
||||
* -# Evaluate all user-defined functions from FUNCTIONS block
|
||||
* -# Loop over data points (size matches RRF-packed data)
|
||||
* -# Calculate time: t = dataTimeStart + i × dataTimeStep
|
||||
* -# Evaluate theory: P(t) = Func(t, par, funcValues)
|
||||
* -# Store results via fData.AppendTheoryValue()
|
||||
*
|
||||
* <b>Theory Function:</b>
|
||||
* The theory is evaluated directly in the RRF frame. The THEORY block should
|
||||
* specify the low-frequency RRF signal (after transformation), not the
|
||||
* laboratory-frame high-frequency precession.
|
||||
*
|
||||
* Example THEORY block for RRF analysis:
|
||||
* \code
|
||||
* THEORY
|
||||
* asymmetry 1 (amplitude)
|
||||
* simpleGss 2 (Gaussian relaxation)
|
||||
* TFieldCos map1 fun1 (frequency shift, phase)
|
||||
* \endcode
|
||||
*
|
||||
* where the frequency in TFieldCos is the difference frequency (ω - ω_RRF).
|
||||
*
|
||||
* \note Unlike CalcChiSquare(), this method does not return a value.
|
||||
* Results are stored internally in fData.fTheory vector.
|
||||
*
|
||||
* \see CalcChiSquare(), PrepareViewData()
|
||||
*/
|
||||
void PRunSingleHistoRRF::CalcTheory()
|
||||
{
|
||||
@@ -289,9 +451,23 @@ void PRunSingleHistoRRF::CalcTheory()
|
||||
// GetNoOfFitBins (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the number of fitted bins for the current fit range.
|
||||
* \brief Returns the number of bins included in the current fit range.
|
||||
*
|
||||
* <b>return:</b> number of fitted bins.
|
||||
* Triggers CalcNoOfFitBins() to ensure the bin count is current based on
|
||||
* the latest fit range settings, then returns the cached value.
|
||||
*
|
||||
* The number of fit bins is needed for:
|
||||
* - Calculating degrees of freedom: ν = N_bins - N_params
|
||||
* - Reduced χ²: χ²_red = χ² / ν
|
||||
* - Statistical diagnostics and fit quality assessment
|
||||
*
|
||||
* \return Number of RRF-packed bins within [fFitStartTime, fFitEndTime].
|
||||
* This accounts for RRF packing: fewer bins than raw data.
|
||||
*
|
||||
* \note The fit range may be modified during fitting by COMMANDS block
|
||||
* instructions. Always call this method to get the current count.
|
||||
*
|
||||
* \see CalcNoOfFitBins(), SetFitRangeBin()
|
||||
*/
|
||||
UInt_t PRunSingleHistoRRF::GetNoOfFitBins()
|
||||
{
|
||||
@@ -304,15 +480,51 @@ UInt_t PRunSingleHistoRRF::GetNoOfFitBins()
|
||||
// SetFitRangeBin (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Allows to change the fit range on the fly. Used in the COMMAND block.
|
||||
* The syntax of the string is: FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]].
|
||||
* If only one pair of fgb/lgb is given, it is used for all runs in the RUN block section.
|
||||
* If multiple fgb/lgb's are given, the number N has to be the number of RUN blocks in
|
||||
* the msr-file.
|
||||
* \brief Sets fit range using bin-offset syntax from COMMANDS block.
|
||||
*
|
||||
* <p>nXY are offsets which can be used to shift, limit the fit range.
|
||||
* Allows dynamic modification of the fit range during fitting, as specified
|
||||
* in the COMMANDS block. This is used for systematic studies where the fit
|
||||
* range needs to be varied.
|
||||
*
|
||||
* \param fitRange string containing the necessary information.
|
||||
* <b>Syntax:</b>
|
||||
* \code
|
||||
* FIT_RANGE fgb[+n0] lgb[-n1] # single range for all runs
|
||||
* FIT_RANGE fgb+n00 lgb-n01 fgb+n10 lgb-n11 ... # per-run ranges
|
||||
* \endcode
|
||||
*
|
||||
* where:
|
||||
* - \c fgb = first good bin (symbolic, replaced by actual value)
|
||||
* - \c lgb = last good bin (symbolic, replaced by actual value)
|
||||
* - \c +n0 = positive offset added to fgb
|
||||
* - \c -n1 = positive offset subtracted from lgb
|
||||
*
|
||||
* <b>Conversion to Time:</b>
|
||||
* \f[
|
||||
* t_{\rm start} = ({\rm fgb} + n_0 - t_0) \times \Delta t
|
||||
* \f]
|
||||
* \f[
|
||||
* t_{\rm end} = ({\rm lgb} - n_1 - t_0) \times \Delta t
|
||||
* \f]
|
||||
*
|
||||
* where Δt is the raw time resolution (before RRF packing).
|
||||
*
|
||||
* <b>Multiple Run Handling:</b>
|
||||
* - Single pair: Applied to all runs
|
||||
* - Multiple pairs: Must match number of RUN blocks; each run uses its own range
|
||||
* - Run selection: Uses (2 × runNo + 1) to index into token array
|
||||
*
|
||||
* <b>Example:</b>
|
||||
* \code
|
||||
* COMMANDS
|
||||
* FIT_RANGE fgb+100 lgb-500 # start 100 bins after fgb, end 500 bins before lgb
|
||||
* \endcode
|
||||
*
|
||||
* \param fitRange String containing FIT_RANGE specification from COMMANDS block
|
||||
*
|
||||
* \warning Invalid syntax produces error message but does not throw exception.
|
||||
* The previous fit range values are retained on error.
|
||||
*
|
||||
* \see GetProperFitRange(), CalcNoOfFitBins()
|
||||
*/
|
||||
void PRunSingleHistoRRF::SetFitRangeBin(const TString fitRange)
|
||||
{
|
||||
@@ -394,7 +606,37 @@ void PRunSingleHistoRRF::SetFitRangeBin(const TString fitRange)
|
||||
// CalcNoOfFitBins (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the number of fitted bins for the current fit range.
|
||||
* \brief Calculates start/end bin indices from fit time range.
|
||||
*
|
||||
* Converts the fit range from time (μs) to RRF-packed bin indices.
|
||||
* This method is called whenever the fit range may have changed.
|
||||
*
|
||||
* <b>Conversion Formulas:</b>
|
||||
* \f[
|
||||
* i_{\rm start} = \lceil \frac{t_{\rm start} - t_{\rm data,0}}{\Delta t_{\rm data}} \rceil
|
||||
* \f]
|
||||
* \f[
|
||||
* i_{\rm end} = \lfloor \frac{t_{\rm end} - t_{\rm data,0}}{\Delta t_{\rm data}} \rfloor + 1
|
||||
* \f]
|
||||
*
|
||||
* where:
|
||||
* - \f$t_{\rm data,0}\f$ = fData.GetDataTimeStart() (first RRF-packed bin center)
|
||||
* - \f$\Delta t_{\rm data}\f$ = fData.GetDataTimeStep() (RRF-packed bin width)
|
||||
*
|
||||
* <b>Bounds Checking:</b>
|
||||
* - fStartTimeBin clamped to [0, data size)
|
||||
* - fEndTimeBin clamped to [0, data size]
|
||||
* - fNoOfFitBins = 0 if fEndTimeBin <= fStartTimeBin
|
||||
*
|
||||
* <b>Side Effects:</b>
|
||||
* Updates member variables:
|
||||
* - fStartTimeBin: First bin index in fit range (inclusive)
|
||||
* - fEndTimeBin: Last bin index in fit range (exclusive)
|
||||
* - fNoOfFitBins: Number of bins = fEndTimeBin - fStartTimeBin
|
||||
*
|
||||
* \note Time step includes RRF packing: dataTimeStep = rawTimeRes × fRRFPacking
|
||||
*
|
||||
* \see GetNoOfFitBins(), SetFitRangeBin()
|
||||
*/
|
||||
void PRunSingleHistoRRF::CalcNoOfFitBins()
|
||||
{
|
||||
@@ -416,17 +658,50 @@ void PRunSingleHistoRRF::CalcNoOfFitBins()
|
||||
// PrepareData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Prepare data for fitting or viewing. What is already processed at this stage:
|
||||
* -# get proper raw run data
|
||||
* -# get all needed forward histograms
|
||||
* -# get time resolution
|
||||
* -# get t0's and perform necessary cross checks (e.g. if t0 of msr-file (if present) are consistent with t0 of the data files, etc.)
|
||||
* -# add runs (if addruns are present)
|
||||
* -# group histograms (if grouping is present)
|
||||
* \brief Main data preparation orchestrator for RRF single histogram analysis.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if everthing went smooth
|
||||
* - false, otherwise.
|
||||
* Coordinates the loading and preprocessing of histogram data before RRF
|
||||
* transformation. This method handles all operations common to both fitting
|
||||
* and viewing modes.
|
||||
*
|
||||
* <b>Processing Steps:</b>
|
||||
* -# Validate object state (return false if already marked invalid)
|
||||
* -# Get GLOBAL block reference for settings
|
||||
* -# Load raw run data from data handler using run name from MSR file
|
||||
* -# Extract metadata from data file:
|
||||
* - Magnetic field (fMetaData.fField)
|
||||
* - Beam energy (fMetaData.fEnergy)
|
||||
* - Sample temperature(s) (fMetaData.fTemp)
|
||||
* -# Collect histogram numbers from RUN block forward specification
|
||||
* -# Validate all specified histograms exist in data file
|
||||
* -# Determine time resolution: ns → μs conversion
|
||||
* -# Determine t0 values via GetProperT0()
|
||||
* -# Initialize forward histogram from first group
|
||||
* -# Handle addrun (co-add multiple runs with t0 alignment)
|
||||
* -# Handle grouping (combine multiple detectors with t0 alignment)
|
||||
* -# Determine data range via GetProperDataRange()
|
||||
* -# Determine fit range via GetProperFitRange()
|
||||
* -# Dispatch to PrepareFitData() or PrepareViewData() based on tag
|
||||
*
|
||||
* <b>Run Addition (addrun):</b>
|
||||
* When multiple runs are specified in the RUN block, histograms are co-added
|
||||
* with t0 alignment:
|
||||
* \code
|
||||
* fForward[i] += addRunData[i + addT0 - mainT0]
|
||||
* \endcode
|
||||
*
|
||||
* <b>Detector Grouping:</b>
|
||||
* When multiple forward histograms are specified, they are summed with
|
||||
* t0 alignment to form a single combined histogram.
|
||||
*
|
||||
* \return true if data preparation succeeds, false on any error:
|
||||
* - Run data not found
|
||||
* - Histogram not present in data file
|
||||
* - Invalid t0 determination
|
||||
* - Data range validation failure
|
||||
* - Fit/view data preparation failure
|
||||
*
|
||||
* \see PrepareFitData(), PrepareViewData(), GetProperT0(), GetProperDataRange()
|
||||
*/
|
||||
Bool_t PRunSingleHistoRRF::PrepareData()
|
||||
{
|
||||
@@ -492,6 +767,7 @@ Bool_t PRunSingleHistoRRF::PrepareData()
|
||||
// check if there are runs to be added to the current one
|
||||
if (fRunInfo->GetRunNameSize() > 1) { // runs to be added present
|
||||
PRawRunData *addRunData;
|
||||
std::vector<PDoubleVector> addForward;
|
||||
for (UInt_t i=1; i<fRunInfo->GetRunNameSize(); i++) {
|
||||
|
||||
// get run to be added to the main one
|
||||
@@ -502,15 +778,23 @@ Bool_t PRunSingleHistoRRF::PrepareData()
|
||||
return false;
|
||||
}
|
||||
|
||||
addForward.clear();
|
||||
addForward.resize(histoNo.size()); // resize to number of groups
|
||||
for (UInt_t j=0; j<histoNo.size(); j++) {
|
||||
addForward[j].resize(addRunData->GetDataBin(histoNo[j])->size());
|
||||
addForward[j] = *addRunData->GetDataBin(histoNo[j]);
|
||||
}
|
||||
DeadTimeCorrection(addForward, histoNo);
|
||||
|
||||
// add forward run
|
||||
UInt_t addRunSize;
|
||||
for (UInt_t k=0; k<histoNo.size(); k++) { // fill each group
|
||||
addRunSize = addRunData->GetDataBin(histoNo[k])->size();
|
||||
for (UInt_t j=0; j<addRunData->GetDataBin(histoNo[k])->size(); j++) { // loop over the bin indices
|
||||
addRunSize = addForward[k].size();
|
||||
for (UInt_t j=0; j<addRunSize; j++) { // loop over the bin indices
|
||||
// make sure that the index stays in the proper range
|
||||
if ((static_cast<Int_t>(j)+static_cast<Int_t>(fAddT0s[i-1][k])-static_cast<Int_t>(fT0s[k]) >= 0) &&
|
||||
(j+static_cast<Int_t>(fAddT0s[i-1][k])-static_cast<Int_t>(fT0s[k]) < addRunSize)) {
|
||||
forward[k][j] += addRunData->GetDataBin(histoNo[k])->at(j+static_cast<Int_t>(fAddT0s[i-1][k])-static_cast<Int_t>(fT0s[k]));
|
||||
forward[k][j] += addForward[k][j+static_cast<Int_t>(fAddT0s[i-1][k])-static_cast<Int_t>(fT0s[k])];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -560,21 +844,73 @@ Bool_t PRunSingleHistoRRF::PrepareData()
|
||||
// PrepareFitData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Take the pre-processed data (i.e. grouping and addrun are preformed) and form the RRF histogram for fitting.
|
||||
* The following steps are preformed:
|
||||
* -# get fit start/stop time
|
||||
* -# check that 'first good data bin', 'last good data bin', and 't0' make any sense
|
||||
* -# check how the background shall be handled, i.e. fitted, subtracted from background estimate data range, or subtacted from a given fixed background.
|
||||
* -# estimate N0
|
||||
* -# RRF transformation
|
||||
* -# packing (i.e rebinning)
|
||||
* \brief Performs full RRF transformation on histogram data for fitting.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true, if everything went smooth
|
||||
* - false, otherwise
|
||||
* Takes the pre-processed histogram (grouping and addrun already applied) and
|
||||
* transforms it into RRF asymmetry suitable for fitting. This is the core
|
||||
* method implementing the RRF analysis technique.
|
||||
*
|
||||
* \param runData raw run data handler
|
||||
* \param histoNo forward histogram number
|
||||
* <b>Processing Steps:</b>
|
||||
*
|
||||
* <b>1. Frequency Analysis:</b>
|
||||
* - Calls GetMainFrequency() on raw data to find dominant precession frequency
|
||||
* - Used to determine optimal N₀ estimation window (integer oscillation cycles)
|
||||
* - Prints "optimal packing" suggestion for user reference
|
||||
*
|
||||
* <b>2. Background Handling:</b>
|
||||
* - If fixed background specified: use directly from RUN block
|
||||
* - If background range given: estimate via EstimateBkg()
|
||||
* - If neither: estimate range as [0.1×t0, 0.6×t0] with warning
|
||||
* - Subtract background: N(t) → N(t) - B
|
||||
*
|
||||
* <b>3. Lifetime Correction:</b>
|
||||
* \f[
|
||||
* M(t) = [N(t) - B] \cdot e^{+t/\tau_\mu}
|
||||
* \f]
|
||||
* - Removes exponential decay from signal
|
||||
* - Error: \f$\sigma_M = e^{+t/\tau_\mu} \sqrt{N(t) + \sigma_B^2}\f$
|
||||
* - Weights: \f$w = 1/\sigma_M^2\f$
|
||||
*
|
||||
* <b>4. N₀ Estimation:</b>
|
||||
* - Call EstimateN0() with frequency information
|
||||
* - Uses average of M(t) over integer number of oscillation cycles
|
||||
* - Returns N₀ and its error σ_N₀
|
||||
*
|
||||
* <b>5. Asymmetry Extraction:</b>
|
||||
* \f[
|
||||
* A(t) = \frac{M(t)}{N_0} - 1
|
||||
* \f]
|
||||
* Error propagation:
|
||||
* \f[
|
||||
* \sigma_A(t) = \frac{e^{+t/\tau_\mu}}{N_0} \sqrt{N(t) + \left(\frac{N(t)-B}{N_0}\right)^2 \sigma_{N_0}^2}
|
||||
* \f]
|
||||
*
|
||||
* <b>6. RRF Rotation:</b>
|
||||
* \f[
|
||||
* A_{\rm RRF}(t) = 2 \cdot A(t) \cdot \cos(\omega_{\rm RRF} t + \phi_{\rm RRF})
|
||||
* \f]
|
||||
* - ω_RRF from GLOBAL block (rrf_freq converted to angular frequency)
|
||||
* - φ_RRF from GLOBAL block (rrf_phase in radians)
|
||||
* - Factor 2 compensates for discarded counter-rotating component
|
||||
*
|
||||
* <b>7. RRF Packing:</b>
|
||||
* - Average over fRRFPacking consecutive bins
|
||||
* - Data: \f$A_{\rm packed} = \frac{1}{n}\sum_{i=1}^{n} A_{\rm RRF}(t_i)\f$
|
||||
* - Error: \f$\sigma_{\rm packed} = \frac{\sqrt{2}}{n}\sqrt{\sum_{i=1}^{n} \sigma_A^2(t_i)}\f$
|
||||
* - √2 factor accounts for doubling in RRF rotation
|
||||
*
|
||||
* <b>8. Time Grid Setup:</b>
|
||||
* - Data time start: accounts for packing offset (center of first packed bin)
|
||||
* - Data time step: rawTimeResolution × fRRFPacking
|
||||
*
|
||||
* \param runData Raw run data handler (for background estimation)
|
||||
* \param histoNo Forward histogram number (0-based, for background error messages)
|
||||
*
|
||||
* \return true on success, false on error:
|
||||
* - Background estimation failure
|
||||
* - Invalid bin ranges
|
||||
*
|
||||
* \see PrepareViewData(), GetMainFrequency(), EstimateN0(), EstimateBkg()
|
||||
*/
|
||||
Bool_t PRunSingleHistoRRF::PrepareFitData(PRawRunData* runData, const UInt_t histoNo)
|
||||
{
|
||||
@@ -712,20 +1048,55 @@ Bool_t PRunSingleHistoRRF::PrepareFitData(PRawRunData* runData, const UInt_t his
|
||||
// PrepareViewData (protected)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Take the pre-processed data (i.e. grouping and addrun are preformed) and form the histogram for viewing
|
||||
* with life time correction, i.e. the exponential decay is removed.
|
||||
* <p>The following steps are preformed:
|
||||
* -# check if view packing is whished.
|
||||
* -# check that 'first good data bin', 'last good data bin', and 't0' makes any sense
|
||||
* -# transform data sets (see below).
|
||||
* -# calculate theory
|
||||
* \brief Prepares RRF-transformed data for viewing/plotting.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true, if everything went smooth
|
||||
* - false, otherwise
|
||||
* Takes the pre-processed histogram and prepares both data and theory curves
|
||||
* for display. This method is used when the operation mode is kView rather
|
||||
* than kFit.
|
||||
*
|
||||
* \param runData raw run data handler
|
||||
* \param histoNo forward histogram number
|
||||
* <b>Processing Steps:</b>
|
||||
*
|
||||
* <b>1. Data Preparation:</b>
|
||||
* - Calls PrepareFitData() to perform full RRF transformation
|
||||
* - Data is ready for display after this step
|
||||
*
|
||||
* <b>2. View Packing Check:</b>
|
||||
* - Checks if additional view packing is specified in PLOT block
|
||||
* - If viewPacking > fRRFPacking: additional packing would be applied (TODO)
|
||||
* - If viewPacking < fRRFPacking: warning issued and view packing ignored
|
||||
* (cannot unpack already-packed RRF data)
|
||||
*
|
||||
* <b>3. Theory Grid Setup:</b>
|
||||
* Determines theory evaluation resolution:
|
||||
* - If fTheoAsData = true: theory calculated only at data points
|
||||
* - If fTheoAsData = false: theory calculated on 8× finer grid for smooth curves
|
||||
*
|
||||
* Time grid:
|
||||
* - Theory time start = data time start
|
||||
* - Theory time step = data time step / factor (where factor = 1 or 8)
|
||||
*
|
||||
* <b>4. Theory Evaluation:</b>
|
||||
* - Extract parameter values from MSR parameter list
|
||||
* - Evaluate all user-defined functions from FUNCTIONS block
|
||||
* - Loop over theory grid points
|
||||
* - Evaluate theory: P(t) = Func(t, par, funcValues)
|
||||
* - Apply sanity check: |P(t)| > 10 → set to 0 (dirty hack for edge cases)
|
||||
* - Store results via fData.AppendTheoryValue()
|
||||
*
|
||||
* <b>Theory Function:</b>
|
||||
* The theory is evaluated directly in the RRF frame. The THEORY block should
|
||||
* specify the low-frequency signal after RRF transformation, not the
|
||||
* laboratory-frame high-frequency precession.
|
||||
*
|
||||
* \param runData Raw run data handler (passed to PrepareFitData)
|
||||
* \param histoNo Forward histogram number (passed to PrepareFitData)
|
||||
*
|
||||
* \return true on success, false on error (typically from PrepareFitData)
|
||||
*
|
||||
* \note The 8× theory resolution provides smoother curves for visualization
|
||||
* and better Fourier transforms without affecting fit performance.
|
||||
*
|
||||
* \see PrepareFitData(), CalcTheory()
|
||||
*/
|
||||
Bool_t PRunSingleHistoRRF::PrepareViewData(PRawRunData* runData, const UInt_t histoNo)
|
||||
{
|
||||
@@ -793,21 +1164,52 @@ Bool_t PRunSingleHistoRRF::PrepareViewData(PRawRunData* runData, const UInt_t hi
|
||||
// GetProperT0 (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the proper t0 for the single histogram run.
|
||||
* -# the t0 vector size = number of detectors (grouping) for forward.
|
||||
* -# initialize t0's with -1
|
||||
* -# fill t0's from RUN block
|
||||
* -# if t0's are missing (i.e. t0 == -1), try to fill from the GLOBAL block.
|
||||
* -# if t0's are missing, try t0's from the data file
|
||||
* -# if t0's are missing, try to estimate them
|
||||
* \brief Determines and validates t0 values for all histograms in the run.
|
||||
*
|
||||
* \param runData pointer to the current RUN block entry from the msr-file
|
||||
* \param globalBlock pointer to the GLOBLA block entry from the msr-file
|
||||
* \param histoNo histogram number vector of forward; histoNo = msr-file forward + redGreen_offset - 1
|
||||
* Searches for time-zero (t0) values through a priority cascade and performs
|
||||
* validation. t0 marks the muon arrival time and is critical for proper
|
||||
* timing alignment.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if everthing went smooth
|
||||
* - false, otherwise.
|
||||
* <b>t0 Search Priority:</b>
|
||||
* -# RUN block: t0 values specified in the MSR file RUN block
|
||||
* -# GLOBAL block: fallback t0 values from GLOBAL block
|
||||
* -# Data file: t0 values stored in the raw data file header
|
||||
* -# Automatic estimation: estimated from histogram shape (with warning)
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Initialize fT0s vector with size = number of forward histograms (grouping)
|
||||
* -# Set all t0 values to -1.0 (unset marker)
|
||||
* -# Fill from RUN block if present
|
||||
* -# Fill remaining -1.0 values from GLOBAL block
|
||||
* -# Fill remaining -1.0 values from data file
|
||||
* -# Fill remaining -1.0 values from automatic estimation (with warning)
|
||||
* -# Validate all t0 values are within histogram bounds
|
||||
*
|
||||
* <b>Addrun Handling:</b>
|
||||
* When multiple runs are co-added (addrun), each additional run needs its own
|
||||
* t0 value for proper time alignment:
|
||||
* -# Initialize fAddT0s[runIdx] for each addrun
|
||||
* -# Apply same priority cascade for each addrun
|
||||
* -# Validate addrun t0 values
|
||||
*
|
||||
* <b>Validation:</b>
|
||||
* - t0 must be ≥ 0
|
||||
* - t0 must be < histogram length
|
||||
* - Error message and return false on validation failure
|
||||
*
|
||||
* \param runData Pointer to raw run data for histogram access and data file t0
|
||||
* \param globalBlock Pointer to GLOBAL block for fallback t0 values
|
||||
* \param histoNo Vector of histogram indices (0-based) for forward grouping
|
||||
*
|
||||
* \return true if valid t0 found for all histograms, false on:
|
||||
* - t0 out of histogram bounds
|
||||
* - addrun data not accessible
|
||||
* - addrun t0 validation failure
|
||||
*
|
||||
* \warning Automatic t0 estimation is unreliable for LEM and other specialized
|
||||
* setups. Always specify t0 explicitly for best results.
|
||||
*
|
||||
* \see GetProperDataRange(), PrepareData()
|
||||
*/
|
||||
Bool_t PRunSingleHistoRRF::GetProperT0(PRawRunData* runData, PMsrGlobalBlock *globalBlock, PUIntVector &histoNo)
|
||||
{
|
||||
@@ -931,14 +1333,40 @@ Bool_t PRunSingleHistoRRF::GetProperT0(PRawRunData* runData, PMsrGlobalBlock *gl
|
||||
// GetProperDataRange (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the proper data range, i.e. first/last good bin (fgb/lgb).
|
||||
* -# get fgb/lgb from the RUN block
|
||||
* -# if fgb/lgb still undefined, try to get it from the GLOBAL block
|
||||
* -# if fgb/lgb still undefined, try to estimate them.
|
||||
* \brief Determines valid data range (first/last good bins) for analysis.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if everthing went smooth
|
||||
* - false, otherwise.
|
||||
* Establishes the boundaries of usable histogram data through a priority
|
||||
* cascade. The data range defines which bins contain valid signal (after t0,
|
||||
* before noise/overflow).
|
||||
*
|
||||
* <b>Data Range Search Priority:</b>
|
||||
* -# RUN block: data range specified in MSR file RUN block
|
||||
* -# GLOBAL block: fallback data range from GLOBAL block
|
||||
* -# Automatic estimation: estimate from t0 (with warning)
|
||||
* - Start: t0 + 10 ns offset
|
||||
* - End: histogram length
|
||||
*
|
||||
* <b>Validation:</b>
|
||||
* -# Check start < end (swap if reversed)
|
||||
* -# Check start ≥ 0 and start < histogram size
|
||||
* -# Check end ≥ 0 (adjust if > histogram size with warning)
|
||||
*
|
||||
* <b>Result:</b>
|
||||
* Sets fGoodBins[0] (first good bin) and fGoodBins[1] (last good bin).
|
||||
* These are used for:
|
||||
* - RRF transformation range
|
||||
* - Fit range specification in bins (fgb+n0 lgb-n1)
|
||||
* - Data validity checking
|
||||
*
|
||||
* \return true if valid data range determined, false on:
|
||||
* - Start bin out of bounds
|
||||
* - End bin negative
|
||||
* - Other range validation failures
|
||||
*
|
||||
* \note The data range is typically wider than the fit range. Data range
|
||||
* defines where valid data exists; fit range defines what is fitted.
|
||||
*
|
||||
* \see GetProperFitRange(), GetProperT0()
|
||||
*/
|
||||
Bool_t PRunSingleHistoRRF::GetProperDataRange()
|
||||
{
|
||||
@@ -1019,16 +1447,45 @@ Bool_t PRunSingleHistoRRF::GetProperDataRange()
|
||||
// GetProperFitRange (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Get the proper fit range. There are two possible fit range commands:
|
||||
* fit <start> <end> given in (usec), or
|
||||
* fit fgb+offset_0 lgb-offset_1 given in (bins), therefore it works the following way:
|
||||
* -# get fit range assuming given in time from RUN block
|
||||
* -# if fit range in RUN block is given in bins, replace start/end
|
||||
* -# if fit range is NOT given yet, try fit range assuming given in time from GLOBAL block
|
||||
* -# if fit range in GLOBAL block is given in bins, replace start/end
|
||||
* -# if still no fit range is given, use fgb/lgb.
|
||||
* \brief Determines fit time range from MSR file settings.
|
||||
*
|
||||
* \param globalBlock pointer to the GLOBAL block information form the msr-file.
|
||||
* Extracts the fit range (time window for parameter extraction) through a
|
||||
* priority cascade. Supports both time-based and bin-based specifications.
|
||||
*
|
||||
* <b>Fit Range Formats:</b>
|
||||
* - Time-based: \c fit \c 0.1 \c 8.0 (in microseconds relative to t0)
|
||||
* - Bin-based: \c fit \c fgb+100 \c lgb-500 (bins relative to good bins)
|
||||
*
|
||||
* <b>Search Priority:</b>
|
||||
* -# RUN block time-based fit range
|
||||
* -# RUN block bin-based fit range (converted to time)
|
||||
* -# GLOBAL block time-based fit range
|
||||
* -# GLOBAL block bin-based fit range (converted to time)
|
||||
* -# Default to data range (fgb to lgb) with warning
|
||||
*
|
||||
* <b>Bin-to-Time Conversion:</b>
|
||||
* \f[
|
||||
* t_{\rm start} = ({\rm fgb} + n_0 - t_0) \times \Delta t
|
||||
* \f]
|
||||
* \f[
|
||||
* t_{\rm end} = ({\rm lgb} - n_1 - t_0) \times \Delta t
|
||||
* \f]
|
||||
*
|
||||
* where Δt = fTimeResolution (raw, before RRF packing).
|
||||
*
|
||||
* <b>Result:</b>
|
||||
* Sets fFitStartTime and fFitEndTime in microseconds relative to t0.
|
||||
* These define the range used in χ² calculation.
|
||||
*
|
||||
* \param globalBlock Pointer to GLOBAL block for fallback fit range settings
|
||||
*
|
||||
* \note The converted time values are written back to the MSR data structures
|
||||
* for log file output consistency.
|
||||
*
|
||||
* \warning If no fit range is specified, the full data range is used with
|
||||
* a warning message. This may not be appropriate for all analyses.
|
||||
*
|
||||
* \see GetProperDataRange(), SetFitRangeBin(), CalcNoOfFitBins()
|
||||
*/
|
||||
void PRunSingleHistoRRF::GetProperFitRange(PMsrGlobalBlock *globalBlock)
|
||||
{
|
||||
@@ -1067,9 +1524,41 @@ void PRunSingleHistoRRF::GetProperFitRange(PMsrGlobalBlock *globalBlock)
|
||||
// GetMainFrequency (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>gets the maximum frequency of the given data.
|
||||
* \brief Finds the dominant precession frequency in raw histogram data.
|
||||
*
|
||||
* \param raw data set.
|
||||
* Performs Fourier analysis on the raw histogram to identify the main muon
|
||||
* spin precession frequency. This is essential for:
|
||||
* - Determining optimal N₀ estimation window (integer oscillation cycles)
|
||||
* - Calculating suggested "optimal packing" for user information
|
||||
* - Validating that the RRF frequency is appropriate
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Create ROOT TH1F histogram from data in good bin range [fGoodBins[0], fGoodBins[1]]
|
||||
* -# Set histogram binning to match time structure
|
||||
* -# Apply Fourier transform using PFourier class
|
||||
* -# Use strong apodization (windowing) to reduce spectral leakage
|
||||
* -# Search power spectrum for maximum above 10 MHz (ignores DC component)
|
||||
* -# Return frequency at maximum power
|
||||
*
|
||||
* <b>Frequency Search Constraints:</b>
|
||||
* - Ignores frequencies below 10 MHz (DC and low-frequency noise)
|
||||
* - Searches for local maximum (rising then falling power)
|
||||
* - Returns 0 if no clear maximum found
|
||||
*
|
||||
* <b>Output Information:</b>
|
||||
* The method prints diagnostic information:
|
||||
* - Detected maximum frequency (MHz)
|
||||
* - Suggested optimal packing for ~5-8 points per cycle
|
||||
*
|
||||
* \param data Raw histogram data vector (counts per bin)
|
||||
*
|
||||
* \return Maximum frequency in MHz, or 0 if no maximum found above 10 MHz.
|
||||
*
|
||||
* \note The frequency is used to determine the N₀ estimation window:
|
||||
* window = ceil(fN0EstimateEndTime × freqMax / 2π) × (2π / freqMax)
|
||||
* This ensures an integer number of complete oscillation cycles.
|
||||
*
|
||||
* \see EstimateN0(), PrepareFitData()
|
||||
*/
|
||||
Double_t PRunSingleHistoRRF::GetMainFrequency(PDoubleVector &data)
|
||||
{
|
||||
@@ -1117,9 +1606,50 @@ Double_t PRunSingleHistoRRF::GetMainFrequency(PDoubleVector &data)
|
||||
// EstimateN0 (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Estimate the N0 for the given run.
|
||||
* \brief Estimates initial normalization N₀ from lifetime-corrected histogram data.
|
||||
*
|
||||
* \param errN0
|
||||
* Calculates N₀ by averaging the lifetime-corrected signal M(t) over an initial
|
||||
* time window. The window is chosen to span an integer number of complete
|
||||
* precession cycles to minimize bias from oscillations.
|
||||
*
|
||||
* <b>N₀ Estimation Formula:</b>
|
||||
* \f[
|
||||
* N_0 = \frac{1}{n} \sum_{i=0}^{n-1} M(t_i)
|
||||
* \f]
|
||||
*
|
||||
* where M(t) = [N(t) - B] × exp(+t/τ_μ) is the lifetime-corrected histogram
|
||||
* stored in fM vector.
|
||||
*
|
||||
* <b>Window Determination:</b>
|
||||
* The end bin is calculated to include an integer number of oscillation cycles:
|
||||
* \f[
|
||||
* n_{\rm end} = {\rm round}\left( \left\lceil \frac{T \cdot f_{\rm max}}{2\pi} \right\rceil \cdot \frac{2\pi}{f_{\rm max} \cdot \Delta t} \right)
|
||||
* \f]
|
||||
*
|
||||
* where:
|
||||
* - T = fN0EstimateEndTime (default 1.0 μs)
|
||||
* - f_max = main precession frequency from GetMainFrequency()
|
||||
* - Δt = fTimeResolution
|
||||
*
|
||||
* <b>Error Estimation:</b>
|
||||
* \f[
|
||||
* \sigma_{N_0} = \frac{\sqrt{\sum_{i=0}^{n-1} w_i^2 \sigma_{M_i}^2}}{\sum_{i=0}^{n-1} w_i}
|
||||
* \f]
|
||||
*
|
||||
* where w_i = 1/σ_M_i² are the weights stored in fW vector.
|
||||
*
|
||||
* <b>Output Information:</b>
|
||||
* Prints diagnostic message: "N₀ = value (error)"
|
||||
*
|
||||
* \param errN0 [out] Reference to store the estimated error on N₀
|
||||
* \param freqMax Main precession frequency (MHz) from GetMainFrequency()
|
||||
*
|
||||
* \return Estimated N₀ value (counts × exp(+t/τ))
|
||||
*
|
||||
* \note The simple average (rather than weighted average) is used for N₀ itself,
|
||||
* while the error uses the full weight information.
|
||||
*
|
||||
* \see GetMainFrequency(), PrepareFitData()
|
||||
*/
|
||||
Double_t PRunSingleHistoRRF::EstimateN0(Double_t &errN0, Double_t freqMax)
|
||||
{
|
||||
@@ -1152,13 +1682,47 @@ Double_t PRunSingleHistoRRF::EstimateN0(Double_t &errN0, Double_t freqMax)
|
||||
// EstimatBkg (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Estimate the background for a given interval.
|
||||
* \brief Estimates background level and error from pre-t0 histogram bins.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true, if everything went smooth
|
||||
* - false, otherwise
|
||||
* Calculates the background (random coincidences, accidentals) from a
|
||||
* specified range of histogram bins, typically before t0. The background
|
||||
* range is adjusted to span an integer number of accelerator RF cycles
|
||||
* for proper averaging.
|
||||
*
|
||||
* \param histoNo forward histogram number of the run
|
||||
* <b>Accelerator RF Periods:</b>
|
||||
* - PSI: ACCEL_PERIOD_PSI ns
|
||||
* - RAL: ACCEL_PERIOD_RAL ns
|
||||
* - TRIUMF: ACCEL_PERIOD_TRIUMF ns
|
||||
* - Unknown: no RF adjustment
|
||||
*
|
||||
* <b>Algorithm:</b>
|
||||
* -# Get background range [start, end] from RUN block
|
||||
* -# Swap start/end if in wrong order (with message)
|
||||
* -# Determine accelerator RF period from institute name
|
||||
* -# Adjust end to span integer number of RF cycles
|
||||
* -# Validate range is within histogram bounds
|
||||
* -# Calculate mean background:
|
||||
* \f$ B = \frac{1}{n}\sum_{i={\rm start}}^{{\rm end}} N(i) \f$
|
||||
* -# Calculate background error (standard deviation):
|
||||
* \f$ \sigma_B = \sqrt{\frac{1}{n-1}\sum_{i={\rm start}}^{{\rm end}} (N(i) - B)^2} \f$
|
||||
* -# Store results in fBackground and fBkgErr
|
||||
* -# Update RUN block with estimated background value
|
||||
*
|
||||
* <b>Output Information:</b>
|
||||
* Prints diagnostic messages:
|
||||
* - Adjusted background range (if RF adjustment applied)
|
||||
* - Background value and error: "fBackground = value (error)"
|
||||
*
|
||||
* \param histoNo Forward histogram number (for error message context)
|
||||
*
|
||||
* \return true on success, false on error:
|
||||
* - Background start out of histogram bounds
|
||||
* - Background end out of histogram bounds
|
||||
*
|
||||
* \note The RF cycle adjustment ensures proper averaging over the
|
||||
* accelerator bunch structure, reducing systematic bias.
|
||||
*
|
||||
* \see PrepareFitData()
|
||||
*/
|
||||
Bool_t PRunSingleHistoRRF::EstimateBkg(UInt_t histoNo)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -49,15 +49,36 @@ ClassImpQ(PStartupHandler)
|
||||
// It is needed because in certain environments ParseFile does not work but ParseBuffer does.
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p> Replacement for the ParseFile method of TSAXParser.
|
||||
* \brief Replacement for TSAXParser::ParseFile() that uses buffer-based parsing.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - 1 if file cannot be read
|
||||
* - 0 if the file has been parsed successfully
|
||||
* - parse error code otherwise
|
||||
* This function provides a workaround for environments where the standard
|
||||
* TSAXParser::ParseFile() method fails but ParseBuffer() works correctly.
|
||||
* It reads the entire XML file into memory and then parses it as a buffer.
|
||||
*
|
||||
* \param saxParser pointer to a TSAXParser object
|
||||
* \param startup_path_name full path to the XML file to be read
|
||||
* <b>Algorithm:</b>
|
||||
* -# Open XML file in binary mode, positioned at end to determine size
|
||||
* -# Allocate buffer for entire file content
|
||||
* -# Read file into buffer
|
||||
* -# Close file
|
||||
* -# Call saxParser->ParseBuffer() with buffer contents
|
||||
* -# Free buffer memory
|
||||
*
|
||||
* <b>Memory Management:</b>
|
||||
* The function allocates a buffer equal to the file size, which is freed
|
||||
* after parsing completes. For very large XML files, this may consume
|
||||
* significant memory temporarily.
|
||||
*
|
||||
* \param saxParser Pointer to an initialized TSAXParser object. The parser
|
||||
* should have its signal slots connected to a handler object
|
||||
* (e.g., PStartupHandler) before calling this function.
|
||||
* \param startup_path_name Full filesystem path to the XML file to be parsed.
|
||||
*
|
||||
* \return Parse status code:
|
||||
* - 0: Success (file parsed without errors)
|
||||
* - 1: File could not be opened or read
|
||||
* - Other: XML parse error code from TSAXParser::ParseBuffer()
|
||||
*
|
||||
* \see PStartupHandler for the XML content handler implementation
|
||||
*/
|
||||
int parseXmlFile(TSAXParser *saxParser, const char *startup_path_name)
|
||||
{
|
||||
@@ -89,7 +110,40 @@ int parseXmlFile(TSAXParser *saxParser, const char *startup_path_name)
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor. Check if the musrfit_startup.xml file is found in some standard search paths
|
||||
* \brief Constructor that locates and optionally resets the musrfit startup configuration.
|
||||
*
|
||||
* Searches for the musrfit_startup.xml configuration file in standard locations
|
||||
* and initializes the handler. If no file is found, creates a default configuration.
|
||||
*
|
||||
* <b>Search Order:</b>
|
||||
* -# Current working directory: \c ./musrfit_startup.xml
|
||||
* -# User config directory: \c $HOME/.musrfit/musrfit_startup.xml
|
||||
* -# MUSRFITPATH environment variable: \c $MUSRFITPATH/musrfit_startup.xml
|
||||
* -# ROOT installation: \c $ROOTSYS/bin/musrfit_startup.xml (with warning)
|
||||
*
|
||||
* <b>File Creation:</b>
|
||||
* If no startup file is found in any location, a default configuration is
|
||||
* automatically created at \c $HOME/.musrfit/musrfit_startup.xml. This includes:
|
||||
* - Standard PSI facility data paths
|
||||
* - Run name templates for all PSI instruments
|
||||
* - Default Fourier transform settings
|
||||
* - Standard marker and color lists
|
||||
*
|
||||
* <b>Reset Mode:</b>
|
||||
* When reset_startup_file=true and a file is found, the existing file is
|
||||
* overwritten with default content. This is useful for:
|
||||
* - Restoring corrupted configurations
|
||||
* - Updating to new default settings after software updates
|
||||
* - Resetting user customizations to defaults
|
||||
*
|
||||
* \param reset_startup_file If true, overwrites existing startup file with defaults.
|
||||
* If false (default), uses existing file or creates new one.
|
||||
*
|
||||
* \note This constructor only locates the file. Actual XML parsing must be
|
||||
* performed separately by connecting this handler to a TSAXParser and
|
||||
* calling parseXmlFile().
|
||||
*
|
||||
* \see StartupFileFound(), GetStartupFilePath(), WriteDefaultStartupFile()
|
||||
*/
|
||||
PStartupHandler::PStartupHandler(bool reset_startup_file)
|
||||
{
|
||||
@@ -178,7 +232,16 @@ PStartupHandler::PStartupHandler(bool reset_startup_file)
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor
|
||||
* \brief Destructor that releases all allocated configuration data.
|
||||
*
|
||||
* Clears all configuration vectors to free memory:
|
||||
* - fDataPathList: Data file search paths
|
||||
* - fMarkerList: ROOT marker style codes
|
||||
* - fColorList: ROOT color codes
|
||||
* - fRunNameTemplate: Instrument run name patterns
|
||||
*
|
||||
* \note The Fourier defaults structure is a value type and is automatically
|
||||
* cleaned up when the object is destroyed.
|
||||
*/
|
||||
PStartupHandler::~PStartupHandler()
|
||||
{
|
||||
@@ -193,7 +256,25 @@ PStartupHandler::~PStartupHandler()
|
||||
// OnStartDocument
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called on start of the XML file reading. Initializes all necessary variables.
|
||||
* \brief SAX callback invoked at the start of XML document parsing.
|
||||
*
|
||||
* Initializes all configuration variables to default values before parsing
|
||||
* begins. This ensures a clean state even if the same handler is reused.
|
||||
*
|
||||
* <b>Initialization:</b>
|
||||
* - fKey = eEmpty (no active element)
|
||||
* - Fourier defaults:
|
||||
* - fFourierBlockPresent = false
|
||||
* - fUnits = FOURIER_UNIT_GAUSS
|
||||
* - fFourierPower = 0 (no zero-padding)
|
||||
* - fApodization = FOURIER_APOD_NONE
|
||||
* - fPlotTag = FOURIER_PLOT_REAL_AND_IMAG
|
||||
* - fRangeForPhaseCorrection = [-1.0, -1.0] (auto)
|
||||
* - fPlotRange = [-1.0, -1.0] (auto)
|
||||
* - fPhaseIncrement = 1.0 degree
|
||||
*
|
||||
* \note This is a SAX parser callback connected via TQObject signals.
|
||||
* It is automatically called by TSAXParser at document start.
|
||||
*/
|
||||
void PStartupHandler::OnStartDocument()
|
||||
{
|
||||
@@ -216,7 +297,16 @@ void PStartupHandler::OnStartDocument()
|
||||
// OnEndDocument
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called on end of XML file reading.
|
||||
* \brief SAX callback invoked at the end of XML document parsing.
|
||||
*
|
||||
* Finalizes configuration by calling CheckLists() to ensure all required
|
||||
* settings have values. If any list is empty after parsing, it will be
|
||||
* populated with default values.
|
||||
*
|
||||
* \note This is a SAX parser callback connected via TQObject signals.
|
||||
* It is automatically called by TSAXParser when parsing completes.
|
||||
*
|
||||
* \see CheckLists()
|
||||
*/
|
||||
void PStartupHandler::OnEndDocument()
|
||||
{
|
||||
@@ -228,11 +318,33 @@ void PStartupHandler::OnEndDocument()
|
||||
// OnStartElement
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when a XML start element is found. Filters out the needed elements
|
||||
* and sets a proper key.
|
||||
* \brief SAX callback invoked when an XML start element tag is encountered.
|
||||
*
|
||||
* \param str XML element name
|
||||
* \param attributes not used
|
||||
* Identifies the element type and sets the parsing state (fKey) accordingly.
|
||||
* This state is used by OnCharacters() to determine how to process element content.
|
||||
*
|
||||
* <b>Recognized Elements:</b>
|
||||
* - \c data_path → eDataPath (data file search directory)
|
||||
* - \c run_name_template → eRunNameTemplate (with inst attribute extraction)
|
||||
* - \c marker → eMarker (ROOT marker style code)
|
||||
* - \c color → eColor (RGB color specification)
|
||||
* - \c units → eUnits (Fourier frequency units)
|
||||
* - \c fourier_power → eFourierPower (zero-padding power)
|
||||
* - \c apodization → eApodization (windowing function)
|
||||
* - \c plot → ePlot (Fourier plot type)
|
||||
* - \c phase → ePhase (Fourier phase value)
|
||||
* - \c phase_increment → ePhaseIncrement (phase adjustment step)
|
||||
*
|
||||
* <b>Attribute Handling:</b>
|
||||
* For \c run_name_template elements, extracts the \c inst attribute value
|
||||
* and stores it in fCurrentInstrumentName for use when processing the
|
||||
* element content.
|
||||
*
|
||||
* \param str XML element name (tag name without angle brackets)
|
||||
* \param attributes TList of TXMLAttr objects containing element attributes
|
||||
*
|
||||
* \note Unrecognized elements leave fKey unchanged (typically eEmpty),
|
||||
* causing their content to be ignored.
|
||||
*/
|
||||
void PStartupHandler::OnStartElement(const Char_t *str, const TList *attributes)
|
||||
{
|
||||
@@ -270,9 +382,15 @@ void PStartupHandler::OnStartElement(const Char_t *str, const TList *attributes)
|
||||
// OnEndElement
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when a XML end element is found. Resets the handler key.
|
||||
* \brief SAX callback invoked when an XML end element tag is encountered.
|
||||
*
|
||||
* \param str not used
|
||||
* Resets the parsing state (fKey) to eEmpty, indicating that any subsequent
|
||||
* character data should be ignored until the next start element is found.
|
||||
*
|
||||
* \param str XML element name (unused, state is always reset to eEmpty)
|
||||
*
|
||||
* \note The element name parameter is not used because all elements reset
|
||||
* to the same state. This simplifies handling of nested elements.
|
||||
*/
|
||||
void PStartupHandler::OnEndElement(const Char_t *str)
|
||||
{
|
||||
@@ -283,10 +401,53 @@ void PStartupHandler::OnEndElement(const Char_t *str)
|
||||
// OnCharacters
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Content of a given XML element. Filters out the data and feeds them to
|
||||
* the internal variables.
|
||||
* \brief SAX callback invoked with text content between XML element tags.
|
||||
*
|
||||
* \param str XML element string
|
||||
* Processes element content based on the current parsing state (fKey) set
|
||||
* by OnStartElement(). Each element type has specific parsing logic and
|
||||
* validation.
|
||||
*
|
||||
* <b>Element Processing:</b>
|
||||
*
|
||||
* - <b>eDataPath:</b> Adds path string directly to fDataPathList
|
||||
*
|
||||
* - <b>eRunNameTemplate:</b> Creates PRunNameTemplate with current instrument
|
||||
* name and template string, adds to fRunNameTemplate
|
||||
*
|
||||
* - <b>eMarker:</b> Validates numeric string, converts to int, adds to fMarkerList
|
||||
*
|
||||
* - <b>eColor:</b> Parses "R,G,B" format (comma-separated integers 0-255),
|
||||
* converts to ROOT color code via TColor::GetColor(), adds to fColorList
|
||||
*
|
||||
* - <b>eUnits:</b> Maps string to FOURIER_UNIT_* constant:
|
||||
* - "gauss" → FOURIER_UNIT_GAUSS
|
||||
* - "tesla" → FOURIER_UNIT_TESLA
|
||||
* - "mhz" → FOURIER_UNIT_FREQ
|
||||
* - "mc/s" → FOURIER_UNIT_CYCLES
|
||||
*
|
||||
* - <b>eFourierPower:</b> Validates integer 0-20, sets fFourierDefaults.fFourierPower
|
||||
*
|
||||
* - <b>eApodization:</b> Maps string to FOURIER_APOD_* constant:
|
||||
* - "none" → FOURIER_APOD_NONE
|
||||
* - "weak" → FOURIER_APOD_WEAK
|
||||
* - "medium" → FOURIER_APOD_MEDIUM
|
||||
* - "strong" → FOURIER_APOD_STRONG
|
||||
*
|
||||
* - <b>ePlot:</b> Maps string to FOURIER_PLOT_* constant:
|
||||
* - "real" → FOURIER_PLOT_REAL
|
||||
* - "imag" → FOURIER_PLOT_IMAG
|
||||
* - "real_and_imag" → FOURIER_PLOT_REAL_AND_IMAG
|
||||
* - "power" → FOURIER_PLOT_POWER
|
||||
* - "phase" → FOURIER_PLOT_PHASE
|
||||
*
|
||||
* - <b>ePhase:</b> Validates float, adds to fFourierDefaults.fPhase vector
|
||||
*
|
||||
* - <b>ePhaseIncrement:</b> Validates float, sets fFourierDefaults.fPhaseIncrement
|
||||
*
|
||||
* \param str Text content between XML tags
|
||||
*
|
||||
* \note Invalid values generate warning messages to stderr but do not cause
|
||||
* parsing to fail. The invalid value is simply ignored.
|
||||
*/
|
||||
void PStartupHandler::OnCharacters(const Char_t *str)
|
||||
{
|
||||
@@ -464,9 +625,14 @@ void PStartupHandler::OnCharacters(const Char_t *str)
|
||||
// OnComment
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when a XML comment is found. Not used.
|
||||
* \brief SAX callback invoked when an XML comment is encountered.
|
||||
*
|
||||
* \param str not used.
|
||||
* Currently does nothing. XML comments in the startup file are ignored.
|
||||
*
|
||||
* \param str Comment text content (without \<!-- and --\> delimiters)
|
||||
*
|
||||
* \note Comments in musrfit_startup.xml are for documentation purposes only
|
||||
* and have no effect on configuration.
|
||||
*/
|
||||
void PStartupHandler::OnComment(const Char_t *str)
|
||||
{
|
||||
@@ -477,9 +643,17 @@ void PStartupHandler::OnComment(const Char_t *str)
|
||||
// OnWarning
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when the XML parser emits a warning.
|
||||
* \brief SAX callback invoked when the XML parser generates a warning.
|
||||
*
|
||||
* \param str warning string
|
||||
* Outputs the warning message to stderr with a "PStartupHandler **WARNING**"
|
||||
* prefix. Warnings typically indicate non-fatal issues such as:
|
||||
* - Deprecated XML constructs
|
||||
* - Minor schema violations
|
||||
* - Character encoding issues
|
||||
*
|
||||
* \param str Warning message from the XML parser
|
||||
*
|
||||
* \note Parsing continues after warnings; they do not cause failure.
|
||||
*/
|
||||
void PStartupHandler::OnWarning(const Char_t *str)
|
||||
{
|
||||
@@ -491,9 +665,18 @@ void PStartupHandler::OnWarning(const Char_t *str)
|
||||
// OnError
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when the XML parser emits an error.
|
||||
* \brief SAX callback invoked when the XML parser encounters an error.
|
||||
*
|
||||
* \param str error string
|
||||
* Outputs the error message to stderr with a "PStartupHandler **ERROR**"
|
||||
* prefix. Errors indicate significant parsing problems such as:
|
||||
* - Malformed XML syntax
|
||||
* - Missing required elements
|
||||
* - Invalid attribute values
|
||||
*
|
||||
* \param str Error message from the XML parser
|
||||
*
|
||||
* \note Depending on error severity, parsing may or may not continue.
|
||||
* The configuration may be incomplete after errors.
|
||||
*/
|
||||
void PStartupHandler::OnError(const Char_t *str)
|
||||
{
|
||||
@@ -505,9 +688,19 @@ void PStartupHandler::OnError(const Char_t *str)
|
||||
// OnFatalError
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when the XML parser emits a fatal error.
|
||||
* \brief SAX callback invoked when the XML parser encounters a fatal error.
|
||||
*
|
||||
* \param str fatal error string
|
||||
* Outputs the error message to stderr with a "PStartupHandler **FATAL ERROR**"
|
||||
* prefix. Fatal errors indicate unrecoverable parsing failures such as:
|
||||
* - Document not well-formed (mismatched tags)
|
||||
* - Invalid XML declaration
|
||||
* - Character encoding that cannot be processed
|
||||
*
|
||||
* \param str Fatal error message from the XML parser
|
||||
*
|
||||
* \warning After a fatal error, parsing stops immediately and the configuration
|
||||
* will be incomplete. CheckLists() will provide default values for
|
||||
* missing settings when OnEndDocument() is called.
|
||||
*/
|
||||
void PStartupHandler::OnFatalError(const Char_t *str)
|
||||
{
|
||||
@@ -519,10 +712,17 @@ void PStartupHandler::OnFatalError(const Char_t *str)
|
||||
// OnCdataBlock
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Not used.
|
||||
* \brief SAX callback invoked when a CDATA section is encountered.
|
||||
*
|
||||
* \param str not used
|
||||
* \param len not used
|
||||
* Currently does nothing. CDATA sections in the startup file are not used.
|
||||
* CDATA sections would typically be used for content containing special
|
||||
* characters that would otherwise need escaping.
|
||||
*
|
||||
* \param str CDATA content (without \<![CDATA[ and ]]\> delimiters)
|
||||
* \param len Length of the CDATA content in characters
|
||||
*
|
||||
* \note The musrfit_startup.xml format does not require CDATA sections
|
||||
* as all content uses standard XML escaping where needed.
|
||||
*/
|
||||
void PStartupHandler::OnCdataBlock(const Char_t *str, Int_t len)
|
||||
{
|
||||
@@ -533,8 +733,34 @@ void PStartupHandler::OnCdataBlock(const Char_t *str, Int_t len)
|
||||
// CheckLists
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Check if the default lists are present and if not, feed them with some default settings
|
||||
* \brief Validates configuration lists and populates empty ones with defaults.
|
||||
*
|
||||
* Called at the end of XML parsing (OnEndDocument) to ensure all required
|
||||
* configuration lists have values. If any list is empty after parsing,
|
||||
* it is populated with sensible defaults.
|
||||
*
|
||||
* <b>Default Data Paths:</b>
|
||||
* Standard PSI facility data directories:
|
||||
* - /mnt/data/nemu/his
|
||||
* - /psi.ch/group/lmu/public/data/XXX/his/, where XXX=lem, alc, dolly, flame, gpd, gps, hal, ltf, or vms
|
||||
*
|
||||
* <b>Default Markers:</b>
|
||||
* ROOT TMarker style codes for distinguishing multiple data sets:
|
||||
* - 24 (open circle), 25 (open square), 26 (open triangle)
|
||||
* - 27 (open diamond), 28 (open cross), 29 (full star)
|
||||
* - 30 (open star), 20 (full circle), 21 (full square)
|
||||
* - 22 (full triangle), 23 (full down triangle)
|
||||
* - 2 (thin cross), 3 (thin star), 5 (thin x)
|
||||
*
|
||||
* <b>Default Colors:</b>
|
||||
* Standard plotting colors (RGB → ROOT color code):
|
||||
* - Black (0,0,0), Red (255,0,0), Green (0,255,0)
|
||||
* - Blue (0,0,255), Magenta (255,0,255), Cyan (0,255,255)
|
||||
* - Violet (156,0,255), Yellow-ish (99,101,49)
|
||||
* - Dark Green (49,101,49), Orange (156,48,0)
|
||||
*
|
||||
* \note This method only populates empty lists. If a list has any entries
|
||||
* from the XML file, no defaults are added.
|
||||
*/
|
||||
void PStartupHandler::CheckLists()
|
||||
{
|
||||
@@ -543,14 +769,16 @@ void PStartupHandler::CheckLists()
|
||||
// check if any data path is given
|
||||
if (fDataPathList.size() == 0) {
|
||||
fDataPathList.push_back(TString("/mnt/data/nemu/his"));
|
||||
fDataPathList.push_back(TString("/mnt/data/nemu/wkm"));
|
||||
fDataPathList.push_back(TString("/afs/psi.ch/project/nemu/data/his"));
|
||||
fDataPathList.push_back(TString("/afs/psi.ch/project/nemu/data/wkm"));
|
||||
fDataPathList.push_back(TString("/afs/psi.ch/project/bulkmusr/data/gps"));
|
||||
fDataPathList.push_back(TString("/afs/psi.ch/project/bulkmusr/data/dolly"));
|
||||
fDataPathList.push_back(TString("/afs/psi.ch/project/bulkmusr/data/gpd"));
|
||||
fDataPathList.push_back(TString("/afs/psi.ch/project/bulkmusr/data/ltf"));
|
||||
fDataPathList.push_back(TString("/afs/psi.ch/project/bulkmusr/data/alc"));
|
||||
fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/lem/his/"));
|
||||
fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/alc/his/"));
|
||||
fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/dolly/his/"));
|
||||
fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/flame/his/"));
|
||||
fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/gpd/his/"));
|
||||
fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/gps/his/"));
|
||||
fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/hal/his/"));
|
||||
fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/ltf/his/"));
|
||||
fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/misc/his/"));
|
||||
fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/vms/his/"));
|
||||
}
|
||||
|
||||
// check if any markers are given
|
||||
@@ -590,13 +818,18 @@ void PStartupHandler::CheckLists()
|
||||
// StartupFileExists
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Checks if a file is present on the disc.
|
||||
* \brief Checks if a file exists and is readable at the specified path.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true, if the file is present
|
||||
* - false, otherwise
|
||||
* Attempts to open the file for reading to verify its existence and
|
||||
* accessibility. The file is immediately closed after the check.
|
||||
*
|
||||
* \param fln file name
|
||||
* \param fln Full filesystem path to the file to check
|
||||
*
|
||||
* \return true if file exists and can be opened for reading,
|
||||
* false if file does not exist or cannot be accessed
|
||||
*
|
||||
* \note This method uses std::ifstream for portability across platforms.
|
||||
* It only checks readability, not write permissions.
|
||||
*/
|
||||
Bool_t PStartupHandler::StartupFileExists(Char_t *fln)
|
||||
{
|
||||
@@ -617,6 +850,52 @@ Bool_t PStartupHandler::StartupFileExists(Char_t *fln)
|
||||
//--------------------------------------------------------------------------
|
||||
// WriteDefaultStartupFile
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* \brief Creates or overwrites a startup configuration file with default content.
|
||||
*
|
||||
* Writes a complete musrfit_startup.xml file containing comprehensive default
|
||||
* settings for the musrfit package. This method is called when:
|
||||
* - No startup file is found in any search location
|
||||
* - User requests reset of existing configuration (reset_startup_file=true)
|
||||
*
|
||||
* <b>File Location:</b>
|
||||
* - If reset_startup_file=true: Overwrites file at fStartupFilePath
|
||||
* - If reset_startup_file=false: Creates new file at $HOME/.musrfit/musrfit_startup.xml
|
||||
* (creates .musrfit directory if it doesn't exist)
|
||||
*
|
||||
* <b>Default Content Includes:</b>
|
||||
*
|
||||
* <b>Data Paths:</b>
|
||||
* - PSI LEM, GPS, GPD, Dolly, Flame, HIFI, LTF, ALC data directories
|
||||
* - Both local mount points and NFS paths
|
||||
*
|
||||
* <b>Run Name Templates:</b>
|
||||
* - Templates for all PSI μSR instruments (GPS, GPD, Dolly, Flame, etc.)
|
||||
* - Templates for various data formats (ROOT, binary, MDU)
|
||||
* - Year and run number placeholder patterns
|
||||
*
|
||||
* <b>Fourier Settings:</b>
|
||||
* - Units: Gauss
|
||||
* - Fourier power: 0 (no zero-padding)
|
||||
* - Apodization: none
|
||||
* - Plot type: real_and_imag
|
||||
* - Phase: 0.0 degrees
|
||||
* - Phase increment: 1.0 degree
|
||||
*
|
||||
* <b>ROOT Settings:</b>
|
||||
* - Marker list: 14 distinct marker styles
|
||||
* - Color list: 10 distinct colors (RGB format)
|
||||
*
|
||||
* \param reset_startup_file If true, overwrites existing file at fStartupFilePath.
|
||||
* If false, creates new file at $HOME/.musrfit/musrfit_startup.xml.
|
||||
*
|
||||
* \return true if file was successfully written, false on error:
|
||||
* - $HOME environment variable not set
|
||||
* - Cannot create .musrfit directory
|
||||
* - Cannot open file for writing
|
||||
*
|
||||
* \see PStartupHandler() constructor, CheckLists()
|
||||
*/
|
||||
Bool_t PStartupHandler::WriteDefaultStartupFile(bool reset_startup_file)
|
||||
{
|
||||
Char_t startup_path_name[256];
|
||||
@@ -657,28 +936,28 @@ Bool_t PStartupHandler::WriteDefaultStartupFile(bool reset_startup_file)
|
||||
|
||||
// write default musrfit_startup.xml
|
||||
fout << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
|
||||
fout << "<musrfit xmlns=\"http://lmu.web.psi.ch/musrfit/user/MUSR/WebHome.html\">" << std::endl;
|
||||
fout << "<musrfit xmlns=\"https://lmu.pages.psi.ch/musrfit-docu/\">" << std::endl;
|
||||
fout << " <comment>" << std::endl;
|
||||
fout << " Defines default settings for the musrfit package" << std::endl;
|
||||
fout << " </comment>" << std::endl;
|
||||
fout << " <data_path>/psi.ch/group/lmu/public/data/lem/his</data_path>" << std::endl;
|
||||
fout << " <data_path>/afs/psi.ch/project/nemu/data/his</data_path>" << std::endl;
|
||||
fout << " <data_path>/afs/psi.ch/project/nemu/data/wkm</data_path>" << std::endl;
|
||||
fout << " <data_path>/afs/psi.ch/project/bulkmusr/data/misc</data_path>" << std::endl;
|
||||
fout << " <data_path>/afs/psi.ch/project/bulkmusr/data/gps</data_path>" << std::endl;
|
||||
fout << " <data_path>/afs/psi.ch/project/bulkmusr/data/dolly</data_path>" << std::endl;
|
||||
fout << " <data_path>/afs/psi.ch/project/bulkmusr/data/gpd</data_path>" << std::endl;
|
||||
fout << " <data_path>/afs/psi.ch/project/bulkmusr/data/ltf</data_path>" << std::endl;
|
||||
fout << " <data_path>/afs/psi.ch/project/bulkmusr/data/alc/td</data_path>" << std::endl;
|
||||
fout << " <data_path>/afs/psi.ch/project/bulkmusr/data/hifi</data_path>" << std::endl;
|
||||
fout << " <data_path>/afs/psi.ch/project/bulkmusr/data/lem</data_path>" << std::endl;
|
||||
fout << " <data_path>/afs/psi.ch/project/bulkmusr/data/flame</data_path>" << std::endl;
|
||||
fout << " <data_path>/psi.ch/group/lmu/public/data/alc/his</data_path>" << std::endl;
|
||||
fout << " <data_path>/psi.ch/group/lmu/public/data/dolly/his</data_path>" << std::endl;
|
||||
fout << " <data_path>/psi.ch/group/lmu/public/data/flame/his</data_path>" << std::endl;
|
||||
fout << " <data_path>/psi.ch/group/lmu/public/data/gpd/his</data_path>" << std::endl;
|
||||
fout << " <data_path>/psi.ch/group/lmu/public/data/gps/his</data_path>" << std::endl;
|
||||
fout << " <data_path>/psi.ch/group/lmu/public/data/hal/his</data_path>" << std::endl;
|
||||
fout << " <data_path>/psi.ch/group/lmu/public/data/ltf/his</data_path>" << std::endl;
|
||||
fout << " <data_path>/psi.ch/group/lmu/public/data/misc/his</data_path>" << std::endl;
|
||||
fout << " <data_path>/psi.ch/group/lmu/public/data/vms/his</data_path>" << std::endl;
|
||||
fout << " <!-- MISC/PSI 1985 - 1990 -->" << std::endl;
|
||||
fout << " <run_name_template inst=\"misc\">d%yyyy%/deltat_misc_%rrrr%.bin</run_name_template>" << std::endl;
|
||||
fout << " <!-- ALC TD/PSI -->" << std::endl;
|
||||
fout << " <run_name_template inst=\"alc\">d%yyyy%/deltat_zh_chem_%rrrr%.bin</run_name_template>" << std:: endl;
|
||||
fout << " <run_name_template inst=\"alc\">d%yyyy%/deltat_tdc_alc_%rrrr%.bin</run_name_template>" << std::endl;
|
||||
fout << " <run_name_template inst=\"alc\">d%yyyy%/tdc/deltat_tdc_alc_%rrrr%.bin</run_name_template>" << std::endl;
|
||||
fout << " <!-- VMS/PSI -->" << std::endl;
|
||||
fout << " <run_name_template inst=\"vms\">d%yyyy%/tdc/root/deltat_tdc_vms_%yyyy%_%rrrr%.root</run_name_template>" << std::endl;
|
||||
fout << " <!-- Dolly/PSI -->" << std::endl;
|
||||
fout << " <run_name_template inst=\"dolly\">d%yyyy%/tdc/root/deltat_tdc_dolly_%yyyy%_%rrrr%.root</run_name_template>" << std::endl;
|
||||
fout << " <run_name_template inst=\"dolly\">d%yyyy%/pie1/deltat_flc_%rrrr%.bin</run_name_template>" << std::endl;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -53,16 +53,18 @@ extern std::vector<void*> gGlobalUserFcn;
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p> Constructor.
|
||||
* \brief Parses the THEORY block and builds a binary expression tree.
|
||||
*
|
||||
* <p> The theory block his parsed and mapped to a tree. Every line (except the '+')
|
||||
* is a theory object by itself, i.e. the whole theory is build up recursivly.
|
||||
* Example:
|
||||
* The constructor recursively parses the theory block from the MSR file and
|
||||
* builds a binary tree structure. Each theory function becomes a node, with
|
||||
* multiplication creating right children and addition creating left children.
|
||||
*
|
||||
* <b>Example Theory Block:</b>
|
||||
* \verbatim
|
||||
Theory block:
|
||||
a 1
|
||||
tf 2 3
|
||||
se 4
|
||||
THEORY
|
||||
a 1 # asymmetry
|
||||
tf 2 3 # TFieldCos (phase, frequency)
|
||||
se 4 # simpleExp (rate)
|
||||
+
|
||||
a 5
|
||||
tf 6 7
|
||||
@@ -72,7 +74,7 @@ extern std::vector<void*> gGlobalUserFcn;
|
||||
tf 10 11
|
||||
\endverbatim
|
||||
*
|
||||
* <p> This is mapped into the following binary tree:
|
||||
* <b>Resulting Binary Tree:</b>
|
||||
* \verbatim
|
||||
a 1
|
||||
+/ \*
|
||||
@@ -85,11 +87,40 @@ extern std::vector<void*> gGlobalUserFcn;
|
||||
se 8
|
||||
\endverbatim
|
||||
*
|
||||
* \param msrInfo msr-file handler
|
||||
* \param runNo msr-file run number
|
||||
* \param hasParent flag needed in order to know if PTheory is the root object or a child
|
||||
* false (default) means this is the root object
|
||||
* true means this is part of an already existing object tree
|
||||
* The tree is evaluated as: (a1 * tf23 * se4) + (a5 * tf67 * se8) + (a9 * tf1011)
|
||||
*
|
||||
* <b>Parsing Algorithm:</b>
|
||||
* -# Initialize member variables and static counters (lineNo, depth)
|
||||
* -# Get current line from theory block (skip if beyond end)
|
||||
* -# Remove comments: text after '(' or '#'
|
||||
* -# Tokenize line into function name and parameters
|
||||
* -# Search fgTheoDataBase for function (by name or abbreviation)
|
||||
* -# Validate parameter count (except for polynom and userFcn)
|
||||
* -# For each parameter token:
|
||||
* - If "mapN": resolve via RUN block map vector
|
||||
* - If "funN": get function index + MSR_PARAM_FUN_OFFSET
|
||||
* - Otherwise: direct parameter number (1-based → 0-based)
|
||||
* -# If next line is not '+': increment depth, create fMul child recursively
|
||||
* -# If depth=0 and next line is '+': skip '+', create fAdd child recursively
|
||||
* -# For root node: call MakeCleanAndTidyTheoryBlock() to format output
|
||||
* -# For userFcn: load shared library and instantiate class object
|
||||
*
|
||||
* <b>User Function Handling:</b>
|
||||
* User functions require special parsing:
|
||||
* - Token 1: shared library name (e.g., "libMyFunc.so")
|
||||
* - Token 2: class name (e.g., "TMyFunction")
|
||||
* - Token 3+: parameters
|
||||
* The library is loaded via gSystem->Load() and the class instantiated via
|
||||
* TClass::GetClass()->New().
|
||||
*
|
||||
* \param msrInfo Pointer to MSR file handler (NOT owned, must outlive PTheory)
|
||||
* \param runNo Zero-based run number for map parameter resolution
|
||||
* \param hasParent false (default) for root theory node, true for child nodes.
|
||||
* Controls reset of static line/depth counters.
|
||||
*
|
||||
* \warning Sets fValid=false on errors. Always check IsValid() after construction.
|
||||
*
|
||||
* \see fgTheoDataBase, SearchDataBase(), IsValid()
|
||||
*/
|
||||
PTheory::PTheory(PMsrHandler *msrInfo, UInt_t runNo, const Bool_t hasParent) : fMsrInfo(msrInfo)
|
||||
{
|
||||
@@ -328,7 +359,18 @@ PTheory::PTheory(PMsrHandler *msrInfo, UInt_t runNo, const Bool_t hasParent) : f
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor
|
||||
* \brief Destructor that recursively cleans up the expression tree.
|
||||
*
|
||||
* Releases all resources allocated by this theory node and its children:
|
||||
* -# Clears parameter number vector (fParamNo)
|
||||
* -# Clears user function parameter cache (fUserParam)
|
||||
* -# Clears LF integral caches (fLFIntegral, fDynLFFuncValue)
|
||||
* -# Recursively deletes child nodes via CleanUp()
|
||||
* -# Deletes user function object if present
|
||||
* -# Clears global user function vector
|
||||
*
|
||||
* \note Child nodes (fAdd, fMul) are deleted via CleanUp() which traverses
|
||||
* the entire tree recursively.
|
||||
*/
|
||||
PTheory::~PTheory()
|
||||
{
|
||||
@@ -353,11 +395,22 @@ PTheory::~PTheory()
|
||||
// IsValid
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Checks if the theory tree is valid.
|
||||
* \brief Recursively checks if the entire theory expression tree is valid.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true if valid
|
||||
* - false otherwise
|
||||
* Traverses the binary tree and checks fValid for this node and all
|
||||
* descendant nodes. A theory tree is valid only if ALL nodes are valid.
|
||||
*
|
||||
* <b>Validation logic:</b>
|
||||
* - If fMul and fAdd both exist: return fValid && fMul->IsValid() && fAdd->IsValid()
|
||||
* - If only fMul exists: return fValid && fMul->IsValid()
|
||||
* - If only fAdd exists: return fValid && fAdd->IsValid()
|
||||
* - If leaf node: return fValid
|
||||
*
|
||||
* \return true if this node and all descendants are valid, false otherwise
|
||||
*
|
||||
* \note Should always be called after construction to verify successful parsing.
|
||||
* A single invalid node anywhere in the tree causes the entire theory
|
||||
* to be marked invalid.
|
||||
*/
|
||||
Bool_t PTheory::IsValid()
|
||||
{
|
||||
@@ -379,14 +432,38 @@ Bool_t PTheory::IsValid()
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Evaluates the theory tree.
|
||||
* \brief Evaluates the theory expression tree at a given time point.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - theory value for the given sets of parameters
|
||||
* Recursively evaluates the binary tree, combining function values according
|
||||
* to the tree structure (multiplication for consecutive lines, addition for
|
||||
* '+' separated sections).
|
||||
*
|
||||
* \param t time for single histogram, asymmetry, and mu-minus fits, x-axis value non-muSR fits
|
||||
* \param paramValues vector with the parameters
|
||||
* \param funcValues vector with the functions (i.e. functions of the parameters)
|
||||
* <b>Evaluation Algorithm:</b>
|
||||
* Based on tree structure, one of four cases applies:
|
||||
* -# fMul && fAdd: this_func(t) * fMul->Func(t) + fAdd->Func(t)
|
||||
* -# fMul only: this_func(t) * fMul->Func(t)
|
||||
* -# fAdd only: this_func(t) + fAdd->Func(t)
|
||||
* -# Leaf node: this_func(t)
|
||||
*
|
||||
* <b>Parameter Resolution:</b>
|
||||
* Within each function, parameters are accessed via fParamNo indices:
|
||||
* - If fParamNo[i] < MSR_PARAM_FUN_OFFSET: use paramValues[fParamNo[i]]
|
||||
* - If fParamNo[i] >= MSR_PARAM_FUN_OFFSET: use funcValues[fParamNo[i] - MSR_PARAM_FUN_OFFSET]
|
||||
*
|
||||
* <b>LF Caching:</b>
|
||||
* Longitudinal field functions (StaticGaussKTLF, DynamicLorentzKTLF, etc.)
|
||||
* use cached integral values that are recalculated only when parameters change.
|
||||
* This is handled transparently within each LF function.
|
||||
*
|
||||
* \param t Time in microseconds for μSR fits, or x-axis value for non-μSR data
|
||||
* \param paramValues Vector of current fit parameter values from FITPARAMETER block
|
||||
* \param funcValues Vector of evaluated function values from FUNCTIONS block
|
||||
*
|
||||
* \return Evaluated polarization/asymmetry value at time t
|
||||
*
|
||||
* \note This method is const but uses mutable members for LF caching.
|
||||
*
|
||||
* \see Constant(), TFCos(), StaticGaussKT(), etc. for individual function implementations
|
||||
*/
|
||||
Double_t PTheory::Func(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
|
||||
{
|
||||
@@ -765,13 +842,22 @@ void PTheory::CleanUp(PTheory *theo)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Searches the internal look up table for the theory name, and if found
|
||||
* set some internal variables to proper values.
|
||||
* \brief Searches fgTheoDataBase for a theory function by name or abbreviation.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - index of the theory function
|
||||
* Performs case-insensitive search through the theory database to find a
|
||||
* matching function. If found, sets fType and fNoOfParam member variables.
|
||||
*
|
||||
* \param name theory name
|
||||
* <b>Search matches either:</b>
|
||||
* - Full function name (e.g., "simplExpo", "TFieldCos")
|
||||
* - Abbreviation (e.g., "se", "tf")
|
||||
*
|
||||
* \param name Function name or abbreviation to search for
|
||||
*
|
||||
* \return Index in fgTheoDataBase (0 to THEORY_MAX-1), or THEORY_UNDEFINED (-1) if not found
|
||||
*
|
||||
* \note Side effects: Sets fType and fNoOfParam when function is found.
|
||||
*
|
||||
* \see fgTheoDataBase
|
||||
*/
|
||||
Int_t PTheory::SearchDataBase(TString name)
|
||||
{
|
||||
@@ -793,11 +879,19 @@ Int_t PTheory::SearchDataBase(TString name)
|
||||
// GetUserFcnIdx (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Counts the number of user functions in the theory block up to lineNo.
|
||||
* \brief Counts user function occurrences in theory block up to a given line.
|
||||
*
|
||||
* <b>return:</b> to number of user functions found up to lineNo
|
||||
* Scans the theory block from line 1 to lineNo (inclusive) and counts
|
||||
* how many lines contain "userFcn". This index is used to:
|
||||
* - Identify which global user function object to use
|
||||
* - Track multiple user functions in a single theory
|
||||
*
|
||||
* \param lineNo current line number in the theory block
|
||||
* \param lineNo Current line number being parsed (1-based in theory block)
|
||||
*
|
||||
* \return Index of current user function (0-based count), or -1 if no userFcn
|
||||
* entries found up to lineNo
|
||||
*
|
||||
* \note The search is case-insensitive ("userFcn", "USERFCN", etc. all match).
|
||||
*/
|
||||
Int_t PTheory::GetUserFcnIdx(UInt_t lineNo) const
|
||||
{
|
||||
@@ -823,10 +917,28 @@ Int_t PTheory::GetUserFcnIdx(UInt_t lineNo) const
|
||||
// MakeCleanAndTidyTheoryBlock private
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Takes the theory block form the msr-file, and makes a nicely formated
|
||||
* theory block.
|
||||
* \brief Reformats the theory block with consistent spacing and comments.
|
||||
*
|
||||
* \param fullTheoryBlock msr-file text lines of the theory block
|
||||
* Processes each line in the theory block to produce clean, well-formatted
|
||||
* output suitable for writing back to MSR files. Formatting includes:
|
||||
* - Function name left-aligned in 10-character field
|
||||
* - Parameters right-aligned in 6-character fields
|
||||
* - Comment string appended showing parameter names
|
||||
*
|
||||
* <b>Example transformation:</b>
|
||||
* \verbatim
|
||||
* Input: "tf 2 3"
|
||||
* Output: "TFieldCos 2 3 (phase frequency)"
|
||||
* \endverbatim
|
||||
*
|
||||
* Special handling for:
|
||||
* - '+' lines: left unchanged
|
||||
* - polynom: delegated to MakeCleanAndTidyPolynom()
|
||||
* - userFcn: delegated to MakeCleanAndTidyUserFcn()
|
||||
*
|
||||
* \param fullTheoryBlock Pointer to theory block lines (modified in place)
|
||||
*
|
||||
* \note Called only by root theory node (hasParent=false) after successful parsing.
|
||||
*/
|
||||
void PTheory::MakeCleanAndTidyTheoryBlock(PMsrLines *fullTheoryBlock)
|
||||
{
|
||||
@@ -914,10 +1026,16 @@ void PTheory::MakeCleanAndTidyTheoryBlock(PMsrLines *fullTheoryBlock)
|
||||
// MakeCleanAndTidyPolynom private
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Prettifies a polynom theory line.
|
||||
* \brief Formats a polynomial theory line with proper spacing.
|
||||
*
|
||||
* \param i line index of the theory polynom line to be prettified
|
||||
* \param fullTheoryBlock msr-file text lines of the theory block
|
||||
* Polynomial functions have variable parameter count, so they require
|
||||
* special formatting. Creates output in format:
|
||||
* \verbatim
|
||||
* polynom tshift p0 p1 p2 ... pn (tshift p0 p1 ... pn)
|
||||
* \endverbatim
|
||||
*
|
||||
* \param i Line index (1-based) in the theory block
|
||||
* \param fullTheoryBlock Pointer to theory block lines (modified in place)
|
||||
*/
|
||||
void PTheory::MakeCleanAndTidyPolynom(UInt_t i, PMsrLines *fullTheoryBlock)
|
||||
{
|
||||
@@ -971,10 +1089,16 @@ void PTheory::MakeCleanAndTidyPolynom(UInt_t i, PMsrLines *fullTheoryBlock)
|
||||
// MakeCleanAndTidyUserFcn private
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Prettifies a user function theory line.
|
||||
* \brief Formats a user function theory line with proper spacing.
|
||||
*
|
||||
* \param i line index of the user function line to be prettified
|
||||
* \param fullTheoryBlock msr-file text lines of the theory block
|
||||
* User functions have variable structure (library, class, parameters),
|
||||
* so they require special formatting. Creates output in format:
|
||||
* \verbatim
|
||||
* userFcn libName.so ClassName param1 param2 ... paramN
|
||||
* \endverbatim
|
||||
*
|
||||
* \param i Line index (1-based) in the theory block
|
||||
* \param fullTheoryBlock Pointer to theory block lines (modified in place)
|
||||
*/
|
||||
void PTheory::MakeCleanAndTidyUserFcn(UInt_t i, PMsrLines *fullTheoryBlock)
|
||||
{
|
||||
@@ -1010,15 +1134,20 @@ void PTheory::MakeCleanAndTidyUserFcn(UInt_t i, PMsrLines *fullTheoryBlock)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p> theory function: Const
|
||||
* \f[ = const \f]
|
||||
* \brief Returns a constant value (baseline, background).
|
||||
*
|
||||
* <b>meaning of paramValues:</b> const
|
||||
* Mathematical form:
|
||||
* \f[ P(t) = c \f]
|
||||
*
|
||||
* <b>return:</b> function value
|
||||
* Used for constant offsets, fixed backgrounds, or baseline corrections.
|
||||
*
|
||||
* \param paramValues vector with the parameters
|
||||
* \param funcValues vector with the functions (i.e. functions of the parameters)
|
||||
* <b>Parameters:</b>
|
||||
* - fParamNo[0]: Constant value c
|
||||
*
|
||||
* \param paramValues Vector of fit parameter values
|
||||
* \param funcValues Vector of evaluated function values
|
||||
*
|
||||
* \return Constant value c
|
||||
*/
|
||||
Double_t PTheory::Constant(const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
|
||||
{
|
||||
@@ -1038,15 +1167,22 @@ Double_t PTheory::Constant(const PDoubleVector& paramValues, const PDoubleVector
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p> theory function: Asymmetry
|
||||
* \f[ = A \f]
|
||||
* \brief Returns the initial asymmetry value.
|
||||
*
|
||||
* <b>meaning of paramValues:</b> \f$A\f$
|
||||
* Mathematical form:
|
||||
* \f[ P(t) = A \f]
|
||||
*
|
||||
* <b>return:</b> function value
|
||||
* The asymmetry represents the initial polarization of the muon beam and is
|
||||
* typically used as a multiplicative prefactor for oscillating/relaxing functions.
|
||||
* Typical values range from 0.15 to 0.30 depending on detector geometry.
|
||||
*
|
||||
* \param paramValues vector with the parameters
|
||||
* \param funcValues vector with the functions (i.e. functions of the parameters)
|
||||
* <b>Parameters:</b>
|
||||
* - fParamNo[0]: Asymmetry value A
|
||||
*
|
||||
* \param paramValues Vector of fit parameter values
|
||||
* \param funcValues Vector of evaluated function values
|
||||
*
|
||||
* \return Asymmetry value A
|
||||
*/
|
||||
Double_t PTheory::Asymmetry(const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
|
||||
{
|
||||
@@ -1066,17 +1202,25 @@ Double_t PTheory::Asymmetry(const PDoubleVector& paramValues, const PDoubleVecto
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p> theory function: simple exponential
|
||||
* \f[ = \exp\left(-\lambda t\right) \f] or
|
||||
* \f[ = \exp\left(-\lambda [t-t_{\rm shift}] \right) \f]
|
||||
* \brief Simple exponential relaxation function.
|
||||
*
|
||||
* <b>meaning of paramValues:</b> \f$\lambda\f$ [, \f$t_{\rm shift}\f$]
|
||||
* Mathematical form:
|
||||
* \f[ P(t) = \exp\left(-\lambda t\right) \f]
|
||||
* or with time shift:
|
||||
* \f[ P(t) = \exp\left(-\lambda [t-t_{\rm shift}] \right) \f]
|
||||
*
|
||||
* <b>return:</b> function value
|
||||
* Represents exponential muon spin relaxation due to dynamic fluctuations
|
||||
* in the fast-fluctuation limit (BPP-type relaxation).
|
||||
*
|
||||
* \param t time in \f$(\mu\mathrm{s})\f$, or x-axis value for non-muSR fit
|
||||
* \param paramValues parameter values
|
||||
* \param funcValues vector with the functions (i.e. functions of the parameters)
|
||||
* <b>Parameters:</b>
|
||||
* - fParamNo[0]: Relaxation rate λ (μs⁻¹)
|
||||
* - fParamNo[1]: (optional) Time shift t_shift (μs)
|
||||
*
|
||||
* \param t Time in μs
|
||||
* \param paramValues Vector of fit parameter values
|
||||
* \param funcValues Vector of evaluated function values
|
||||
*
|
||||
* \return Exponential relaxation value at time t
|
||||
*/
|
||||
Double_t PTheory::SimpleExp(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
|
||||
{
|
||||
@@ -1106,17 +1250,29 @@ Double_t PTheory::SimpleExp(Double_t t, const PDoubleVector& paramValues, const
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p> theory function: generalized exponential
|
||||
* \f[ = \exp\left(-[\lambda t]^\beta\right) \f] or
|
||||
* \f[ = \exp\left(-[\lambda (t-t_{\rm shift})]^\beta\right) \f]
|
||||
* \brief Generalized (stretched) exponential relaxation function.
|
||||
*
|
||||
* <b>meaning of paramValues:</b> \f$\lambda\f$, \f$\beta\f$ [, \f$t_{\rm shift}\f$]
|
||||
* Mathematical form:
|
||||
* \f[ P(t) = \exp\left(-[\lambda t]^\beta\right) \f]
|
||||
* or with time shift:
|
||||
* \f[ P(t) = \exp\left(-[\lambda (t-t_{\rm shift})]^\beta\right) \f]
|
||||
*
|
||||
* <b>return:</b> function value
|
||||
* The stretched exponential (Kohlrausch function) represents relaxation
|
||||
* in systems with a distribution of correlation times:
|
||||
* - β = 1: Simple exponential
|
||||
* - β < 1: Stretched exponential (distributed relaxation)
|
||||
* - β = 2: Gaussian relaxation
|
||||
*
|
||||
* \param t time in \f$(\mu\mathrm{s})\f$, or x-axis value for non-muSR fit
|
||||
* \param paramValues parameter values
|
||||
* \param funcValues vector with the functions (i.e. functions of the parameters)
|
||||
* <b>Parameters:</b>
|
||||
* - fParamNo[0]: Relaxation rate λ (μs⁻¹)
|
||||
* - fParamNo[1]: Stretching exponent β
|
||||
* - fParamNo[2]: (optional) Time shift t_shift (μs)
|
||||
*
|
||||
* \param t Time in μs
|
||||
* \param paramValues Vector of fit parameter values
|
||||
* \param funcValues Vector of evaluated function values
|
||||
*
|
||||
* \return Stretched exponential value at time t
|
||||
*/
|
||||
Double_t PTheory::GeneralExp(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
|
||||
{
|
||||
@@ -1154,17 +1310,26 @@ Double_t PTheory::GeneralExp(Double_t t, const PDoubleVector& paramValues, const
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p> theory function: simple Gaussian
|
||||
* \f[ = \exp\left(-1/2 [\sigma t]^2\right) \f] or
|
||||
* \f[ = \exp\left(-1/2 [\sigma (t-t_{\rm shift})]^2\right) \f]
|
||||
* \brief Simple Gaussian relaxation function.
|
||||
*
|
||||
* <b>meaning of paramValues:</b> \f$\sigma\f$ [, \f$t_{\rm shift}\f$]
|
||||
* Mathematical form:
|
||||
* \f[ P(t) = \exp\left(-\frac{1}{2} [\sigma t]^2\right) \f]
|
||||
* or with time shift:
|
||||
* \f[ P(t) = \exp\left(-\frac{1}{2} [\sigma (t-t_{\rm shift})]^2\right) \f]
|
||||
*
|
||||
* <b>return:</b> function value
|
||||
* Represents Gaussian muon spin relaxation due to static random fields
|
||||
* with a Gaussian distribution. The parameter σ = γ_μ ΔB where ΔB is the
|
||||
* RMS field width.
|
||||
*
|
||||
* \param t time in \f$(\mu\mathrm{s})\f$, or x-axis value for non-muSR fit
|
||||
* \param paramValues parameter values
|
||||
* \param funcValues vector with the functions (i.e. functions of the parameters)
|
||||
* <b>Parameters:</b>
|
||||
* - fParamNo[0]: Relaxation rate σ (μs⁻¹)
|
||||
* - fParamNo[1]: (optional) Time shift t_shift (μs)
|
||||
*
|
||||
* \param t Time in μs
|
||||
* \param paramValues Vector of fit parameter values
|
||||
* \param funcValues Vector of evaluated function values
|
||||
*
|
||||
* \return Gaussian relaxation value at time t
|
||||
*/
|
||||
Double_t PTheory::SimpleGauss(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
|
||||
{
|
||||
@@ -1194,17 +1359,33 @@ Double_t PTheory::SimpleGauss(Double_t t, const PDoubleVector& paramValues, cons
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p> theory function: static Gaussian Kubo-Toyabe in zero applied field
|
||||
* \f[ = \frac{1}{3} + \frac{2}{3} \left[1-(\sigma t)^2\right] \exp\left[-1/2 (\sigma t)^2\right] \f] or
|
||||
* \f[ = \frac{1}{3} + \frac{2}{3} \left[1-(\sigma \{t-t_{\rm shift}\})^2\right] \exp\left[-1/2 (\sigma \{t-t_{\rm shift}\})^2\right] \f]
|
||||
* \brief Static Gaussian Kubo-Toyabe relaxation function in zero field.
|
||||
*
|
||||
* <b>meaning of paramValues:</b> \f$\sigma\f$ [, \f$t_{\rm shift}\f$]
|
||||
* Mathematical form:
|
||||
* \f[ P(t) = \frac{1}{3} + \frac{2}{3} \left[1-(\sigma t)^2\right] \exp\left[-\frac{1}{2} (\sigma t)^2\right] \f]
|
||||
* or with time shift:
|
||||
* \f[ P(t) = \frac{1}{3} + \frac{2}{3} \left[1-(\sigma \{t-t_{\rm shift}\})^2\right] \exp\left[-\frac{1}{2} (\sigma \{t-t_{\rm shift}\})^2\right] \f]
|
||||
*
|
||||
* <b>return:</b> function value
|
||||
* The Kubo-Toyabe function describes muon spin relaxation in a powder sample
|
||||
* with random static nuclear magnetic moments creating a Gaussian field
|
||||
* distribution at the muon site.
|
||||
*
|
||||
* \param t time in \f$(\mu\mathrm{s})\f$, or x-axis value for non-muSR fit
|
||||
* \param paramValues parameter values
|
||||
* \param funcValues vector with the functions (i.e. functions of the parameters)
|
||||
* Physical interpretation:
|
||||
* - 1/3 component: Muons with spin parallel to local field (unrelaxed)
|
||||
* - 2/3 component: Muons with spin perpendicular to local field (relaxing)
|
||||
* - Recovery at long times: Partial repolarization to 1/3
|
||||
*
|
||||
* <b>Parameters:</b>
|
||||
* - fParamNo[0]: Relaxation rate σ = γ_μ ΔB (μs⁻¹), where ΔB is RMS field
|
||||
* - fParamNo[1]: (optional) Time shift t_shift (μs)
|
||||
*
|
||||
* \param t Time in μs
|
||||
* \param paramValues Vector of fit parameter values
|
||||
* \param funcValues Vector of evaluated function values
|
||||
*
|
||||
* \return Gaussian Kubo-Toyabe value at time t
|
||||
*
|
||||
* \see StaticGaussKTLF() for longitudinal field version
|
||||
*/
|
||||
Double_t PTheory::StaticGaussKT(Double_t t, const PDoubleVector& paramValues, const PDoubleVector& funcValues) const
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -35,7 +35,15 @@ ClassImp(PUserFcn)
|
||||
|
||||
//------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor
|
||||
* \brief Default constructor for PUserFcn.
|
||||
*
|
||||
* Initializes a third-order polynomial user function. This implementation
|
||||
* requires no special initialization as it has no internal state - all
|
||||
* computation is done directly in the operator() method.
|
||||
*
|
||||
* \note This simple constructor serves as a template for more complex user
|
||||
* functions. Functions requiring initialization (e.g., loading lookup tables,
|
||||
* precomputing constants) should perform that work here or in SetGlobalPart().
|
||||
*/
|
||||
PUserFcn::PUserFcn()
|
||||
{
|
||||
@@ -43,7 +51,16 @@ PUserFcn::PUserFcn()
|
||||
|
||||
//------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor
|
||||
* \brief Destructor for PUserFcn.
|
||||
*
|
||||
* Cleans up any resources allocated by the polynomial function. Since this
|
||||
* implementation has no dynamically allocated resources, the destructor is
|
||||
* empty.
|
||||
*
|
||||
* \note User functions with allocated resources (lookup tables, buffers,
|
||||
* external library handles) must clean them up here to prevent memory leaks.
|
||||
* If using the global part interface, ensure proper coordination with
|
||||
* gGlobalUserFcn cleanup.
|
||||
*/
|
||||
PUserFcn::~PUserFcn()
|
||||
{
|
||||
@@ -51,16 +68,48 @@ PUserFcn::~PUserFcn()
|
||||
|
||||
//------------------------------------------------------
|
||||
/**
|
||||
* <p> user function example: polynome of 3rd order
|
||||
* \brief Evaluates the third-order polynomial at the given time.
|
||||
*
|
||||
* \f[ = \sum_{k=0}^3 c_k t^k \f]
|
||||
* Computes a cubic polynomial of the form:
|
||||
*
|
||||
* <b>meaning of paramValues:</b> \f$c_0\f$, \f$c_1\f$, \f$c_2\f$, \f$c_3\f$
|
||||
* \f[ P(t) = c_0 + c_1 t + c_2 t^2 + c_3 t^3 = \sum_{k=0}^{3} c_k t^k \f]
|
||||
*
|
||||
* <b>return:</b> function value
|
||||
* where the coefficients \f$c_k\f$ are provided in the parameter vector.
|
||||
*
|
||||
* \param t time in \f$(\mu\mathrm{s})\f$, or x-axis value for non-muSR fit
|
||||
* \param param parameter vector
|
||||
* \section puserfcn_op_example Example MSR Configuration
|
||||
*
|
||||
* \code
|
||||
* FITPARAMETER
|
||||
* # No Name Value Step Pos_Error Boundaries
|
||||
* 1 c0 0.95 0.01 none
|
||||
* 2 c1 -0.001 0.0001 none
|
||||
* 3 c2 0.00001 0.000001 none
|
||||
* 4 c3 0.0 0.0000001 none 0 none (fixed to zero for quadratic)
|
||||
*
|
||||
* THEORY
|
||||
* userFcn libPUserFcn.so PUserFcn 1 2 3 4
|
||||
* \endcode
|
||||
*
|
||||
* \section puserfcn_op_notes Implementation Notes
|
||||
*
|
||||
* - Uses direct polynomial evaluation (Horner's method could improve
|
||||
* numerical stability for high-precision applications)
|
||||
* - Asserts exactly 4 parameters to catch MSR file configuration errors
|
||||
* - No special handling for negative time values
|
||||
*
|
||||
* \param t Independent variable (time in μs for μSR, or general x-axis
|
||||
* value for non-μSR fits)
|
||||
* \param param Vector containing exactly 4 polynomial coefficients:
|
||||
* - param[0]: \f$c_0\f$ - constant term (dimensionless)
|
||||
* - param[1]: \f$c_1\f$ - linear coefficient (μs⁻¹)
|
||||
* - param[2]: \f$c_2\f$ - quadratic coefficient (μs⁻²)
|
||||
* - param[3]: \f$c_3\f$ - cubic coefficient (μs⁻³)
|
||||
*
|
||||
* \return The polynomial value \f$P(t)\f$ at the specified time
|
||||
*
|
||||
* \pre param.size() == 4 (enforced by assertion)
|
||||
*
|
||||
* \see PUserFcnBase::operator() for the virtual interface specification
|
||||
*/
|
||||
Double_t PUserFcn::operator()(Double_t t, const std::vector<Double_t> ¶m) const
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -34,21 +34,58 @@
|
||||
|
||||
ClassImp(PUserFcnBase)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// This function is a replacement for the ParseFile method of TSAXParser.
|
||||
// It is needed because in certain environments ParseFile does not work but ParseBuffer does.
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p> Replacement for the ParseFile method of TSAXParser
|
||||
* that can be used in user functions.
|
||||
* \brief Parses an XML file using buffer-based parsing for better compatibility.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - 1 if file cannot be read
|
||||
* - 0 if the file has been parsed successfully
|
||||
* - parse error code otherwise
|
||||
* This function provides a replacement for TSAXParser::ParseFile() that works
|
||||
* reliably across different environments. Some systems have issues with direct
|
||||
* file parsing, but buffer-based parsing (ParseBuffer) works consistently.
|
||||
*
|
||||
* \param saxParser pointer to a TSAXParser object
|
||||
* \param startup_path_name full path to the XML file to be read
|
||||
* \section parsexml_usage Usage in User Functions
|
||||
*
|
||||
* User functions that need to read XML configuration files should use this
|
||||
* function instead of TSAXParser::ParseFile():
|
||||
*
|
||||
* \code{.cpp}
|
||||
* class TMyConfigurableFcn : public PUserFcnBase {
|
||||
* private:
|
||||
* MyConfigHandler fHandler; // Derived from TSAXParser callbacks
|
||||
*
|
||||
* public:
|
||||
* Bool_t LoadConfig(const char* configFile) {
|
||||
* TSAXParser parser;
|
||||
* parser.ConnectToHandler("MyConfigHandler", &fHandler);
|
||||
*
|
||||
* Int_t status = parseXmlFile(&parser, configFile);
|
||||
* if (status != 0) {
|
||||
* std::cerr << "Failed to parse config: " << configFile << std::endl;
|
||||
* return false;
|
||||
* }
|
||||
* return true;
|
||||
* }
|
||||
* };
|
||||
* \endcode
|
||||
*
|
||||
* \section parsexml_algorithm Algorithm
|
||||
*
|
||||
* 1. Opens the file in binary mode, seeking to end
|
||||
* 2. Determines file size from stream position
|
||||
* 3. Allocates buffer and reads entire file
|
||||
* 4. Passes buffer to TSAXParser::ParseBuffer()
|
||||
* 5. Cleans up buffer memory
|
||||
*
|
||||
* \param saxParser Pointer to a configured TSAXParser object. The parser
|
||||
* should have its handler connected before calling this function.
|
||||
* \param startup_path_name Full filesystem path to the XML file to parse.
|
||||
*
|
||||
* \return Status code:
|
||||
* - 0: Success - file parsed without errors
|
||||
* - 1: File error - could not open or read the file
|
||||
* - >1: XML parse error from TSAXParser::ParseBuffer()
|
||||
*
|
||||
* \see PStartupHandler for an example of XML parsing in musrfit
|
||||
* \see TSAXParser for ROOT's SAX parser documentation
|
||||
*/
|
||||
Int_t parseXmlFile(TSAXParser *saxParser, const char *startup_path_name)
|
||||
{
|
||||
@@ -76,5 +113,43 @@ Int_t parseXmlFile(TSAXParser *saxParser, const char *startup_path_name)
|
||||
return status;
|
||||
}
|
||||
|
||||
// place a void pointer vector for global user function objects which might be needed
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* \brief Global storage for user function objects requiring persistent state.
|
||||
*
|
||||
* This vector provides a global container for user functions that need to
|
||||
* maintain state across multiple evaluations or share data between runs.
|
||||
* It is primarily used by user functions implementing the "global part"
|
||||
* interface (NeedGlobalPart(), SetGlobalPart(), GlobalPartIsValid()).
|
||||
*
|
||||
* \section gGlobalUserFcn_usage Usage Pattern
|
||||
*
|
||||
* User functions with expensive initialization (lookup tables, precomputed
|
||||
* grids, loaded data files) store their global objects here:
|
||||
*
|
||||
* \code{.cpp}
|
||||
* // In user function's SetGlobalPart implementation:
|
||||
* void TMyFcn::SetGlobalPart(std::vector<void*> &globalPart, UInt_t idx) {
|
||||
* if (idx < globalPart.size() && globalPart[idx] != nullptr) {
|
||||
* fGlobal = static_cast<MyGlobalData*>(globalPart[idx]);
|
||||
* } else {
|
||||
* fGlobal = new MyGlobalData();
|
||||
* fGlobal->Initialize(); // Expensive one-time computation
|
||||
* if (idx < globalPart.size())
|
||||
* globalPart[idx] = fGlobal;
|
||||
* else
|
||||
* globalPart.push_back(fGlobal);
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \note The vector stores void pointers, so user functions must cast
|
||||
* appropriately and manage memory for their specific data types.
|
||||
*
|
||||
* \warning User functions are responsible for proper cleanup of their
|
||||
* global objects to avoid memory leaks.
|
||||
*
|
||||
* \see PUserFcnBase::SetGlobalPart() for the interface to populate this vector
|
||||
* \see PTheory for how global parts are initialized during theory setup
|
||||
*/
|
||||
std::vector<void *> gGlobalUserFcn;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
@@ -101,7 +102,7 @@ void dump_header_syntax()
|
||||
std::cout << std::endl << " -s, --summary : this option is used for LE-uSR data sets only. It will, additionally";
|
||||
std::cout << std::endl << " to the header information, print the summary file content.";
|
||||
std::cout << std::endl << " -i, --instrument <inst> : where <inst> is the requested instrument:";
|
||||
std::cout << std::endl << " lem (default) | gps | ltf | dolly | gpd | hifi | flame.";
|
||||
std::cout << std::endl << " lem (default) | gps | ltf | dolly | gpd | hifi | flame | vms.";
|
||||
std::cout << std::endl << " -c, --counts : will show detector counts as well.";
|
||||
std::cout << std::endl << " -h, --help : will show this help";
|
||||
std::cout << std::endl << " -v, --version : will show the current version.";
|
||||
@@ -201,22 +202,39 @@ int dump_header_root(const std::string fileName, const bool summary, const bool
|
||||
std::cout << std::endl << "Detector Info (for all detectors the same): ";
|
||||
std::cout << std::endl << "-------------------";
|
||||
std::cout << std::endl << "Histo Length : " << runHeader->GetNChannels();
|
||||
double *timeZero;
|
||||
double *timeZero = nullptr;
|
||||
timeZero = runHeader->GetTimeZero();
|
||||
std::cout << std::endl << "Time Zero Bin : " << timeZero[0];
|
||||
std::cout << std::endl << "First Good Bin : " << timeZero[0];
|
||||
if (timeZero != nullptr) {
|
||||
std::cout << std::endl << "Time Zero Bin : " << timeZero[0];
|
||||
std::cout << std::endl << "First Good Bin : " << timeZero[0];
|
||||
} else {
|
||||
std::cout << std::endl << "Time Zero Bin : ??";
|
||||
std::cout << std::endl << "First Good Bin : ??";
|
||||
}
|
||||
std::cout << std::endl << "Last Good Bin : " << runHeader->GetNChannels()-1;
|
||||
std::cout << std::endl << "-------------------" << std::endl << std::endl;
|
||||
} else { // MusrRoot
|
||||
// invoke the MusrRoot header object
|
||||
header = std::make_unique<TMusrRunHeader>(fileName.c_str(), true); // read quite
|
||||
if (header == nullptr) {
|
||||
std::cerr << std::endl << "**ERROR** Couldn't invoke MusrRoot RunHeader from file:" << fileName;
|
||||
std::cerr << std::endl;
|
||||
f.Close();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check if TFolder or TDirectory is needed
|
||||
if (fileType == DH_MUSR_ROOT) { // TFolder
|
||||
f.GetObject("RunHeader", folder);
|
||||
if (folder == nullptr) {
|
||||
std::cerr << std::endl << "**ERROR** Couldn't get folder from MusrRoot RunHeader from file:" << fileName;
|
||||
std::cerr << std::endl;
|
||||
f.Close();
|
||||
return 1;
|
||||
}
|
||||
// try to populate the MusrRoot header object
|
||||
if (!header->ExtractAll(folder)) {
|
||||
std::cerr << std::endl << "**ERROR** Couldn't invoke MusrRoot RunHeader in file:" << fileName;
|
||||
std::cerr << std::endl << "**ERROR** Couldn't invoke MusrRoot RunHeader content from file:" << fileName;
|
||||
std::cerr << std::endl;
|
||||
f.Close();
|
||||
return 1;
|
||||
@@ -224,6 +242,12 @@ int dump_header_root(const std::string fileName, const bool summary, const bool
|
||||
} else { // TDirectory
|
||||
TDirectoryFile *runHeader = nullptr;
|
||||
f.GetObject("RunHeader", runHeader);
|
||||
if (runHeader == nullptr) {
|
||||
std::cerr << std::endl << "**ERROR** Couldn't get runHeader (TDirectory) from MusrRoot RunHeader from file:" << fileName;
|
||||
std::cerr << std::endl;
|
||||
f.Close();
|
||||
return 1;
|
||||
}
|
||||
// try to populate the MusrRoot header object
|
||||
if (!header->ExtractAll(runHeader)) {
|
||||
std::cerr << std::endl << "**ERROR** Couldn't invoke MusrRoot RunHeader in file:" << fileName;
|
||||
@@ -247,9 +271,14 @@ int dump_header_root(const std::string fileName, const bool summary, const bool
|
||||
}
|
||||
|
||||
// summary as well?
|
||||
if (summary && (fileType == DH_MUSR_ROOT)) {
|
||||
if (summary && ((fileType == DH_MUSR_ROOT) || (fileType == DH_MUSR_ROOT_DIR))) {
|
||||
TObjArray *runSum=nullptr;
|
||||
runSum = static_cast<TObjArray*>(folder->FindObject("RunSummary"));
|
||||
|
||||
if (fileType == DH_MUSR_ROOT) // TFolder
|
||||
runSum = static_cast<TObjArray*>(folder->FindObject("RunSummary"));
|
||||
else // TDirectory
|
||||
f.GetObject("RunHeader/RunSummary", runSum);
|
||||
|
||||
if (!runSum) { // something is wrong!!
|
||||
std::cerr << std::endl << "**ERROR** Couldn't obtain RunSummary " << fileName << std::endl;
|
||||
f.Close();
|
||||
@@ -337,15 +366,39 @@ int dump_header_root(const std::string fileName, const bool summary, const bool
|
||||
int dump_header_nexus(const std::string fileName, const bool counts) {
|
||||
|
||||
#ifdef PNEXUS_ENABLED
|
||||
std::unique_ptr<PNeXus> nxs_file = std::make_unique<PNeXus>(fileName.c_str());
|
||||
nxs::HDFType type = nxs::checkHDFType(fileName);
|
||||
|
||||
if (nxs_file->IsValid(false)) {
|
||||
nxs_file->Dump(counts);
|
||||
} else {
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "**ERROR** found invalid NeXus file." << std::endl;
|
||||
std::cerr << std::endl;
|
||||
return 1;
|
||||
// check for type errors, missing enabled HDF4
|
||||
switch (type) {
|
||||
case nxs::HDFType::HDF4:
|
||||
std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): HDF4 file." << std::endl;
|
||||
#ifndef HAVE_HDF4
|
||||
std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): **ERROR**, HDF4 is not enabled." << std::endl;
|
||||
return 1;
|
||||
#endif
|
||||
break;
|
||||
case nxs::HDFType::HDF5:
|
||||
std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): HDF5 file." << std::endl;
|
||||
break;
|
||||
case nxs::HDFType::Unknown:
|
||||
std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): Not a valid NeXus file." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (type == nxs::HDFType::HDF4) {
|
||||
#ifdef HAVE_HDF4
|
||||
std::unique_ptr<nxH4::PNeXus> nxs_file = std::make_unique<nxH4::PNeXus>(fileName);
|
||||
if (nxs_file == nullptr) {
|
||||
std::cerr << std::endl << "**ERROR** allocation of nxH4::PNeXus object failed." << std::endl;
|
||||
}
|
||||
nxs_file->Dump();
|
||||
#endif
|
||||
} else { // HDF5
|
||||
std::unique_ptr<nxH5::PNeXus> nxs_file = std::make_unique<nxH5::PNeXus>(fileName);
|
||||
if (nxs_file == nullptr) {
|
||||
std::cerr << std::endl << "**ERROR** allocation of nxH5::PNeXus object failed." << std::endl;
|
||||
}
|
||||
nxs_file->Dump();
|
||||
}
|
||||
#else
|
||||
std::cout << std::endl << "NeXus not enabled, hence the header information cannot be dumped." << std::endl << std::endl;
|
||||
@@ -543,6 +596,7 @@ int dump_header_mud(const std::string fileName, const bool counts)
|
||||
int success;
|
||||
|
||||
char fln[256];
|
||||
memset(fln, '\0', sizeof(fln));
|
||||
strncpy(fln, fileName.c_str(), sizeof(fln));
|
||||
fh = MUD_openRead(fln, &type);
|
||||
if (fh == -1) {
|
||||
@@ -572,9 +626,12 @@ int dump_header_mud(const std::string fileName, const bool counts)
|
||||
tval = static_cast<time_t>(val);
|
||||
if (success) {
|
||||
dt = localtime(static_cast<const time_t*>(&tval));
|
||||
assert(dt);
|
||||
strftime(str, sizeof(str), "%F; %T", dt);
|
||||
std::cout << std::endl << "Run Start Time : " << str;
|
||||
if (dt != nullptr) {
|
||||
strftime(str, sizeof(str), "%F; %T", dt);
|
||||
std::cout << std::endl << "Run Start Time : " << str;
|
||||
} else {
|
||||
std::cout << std::endl << "Run Start Time : ??";
|
||||
}
|
||||
} else {
|
||||
std::cout << std::endl << "Run Start Time : ???";
|
||||
}
|
||||
@@ -583,9 +640,12 @@ int dump_header_mud(const std::string fileName, const bool counts)
|
||||
tval = static_cast<time_t>(val);
|
||||
if (success) {
|
||||
dt = localtime(static_cast<const time_t*>(&tval));
|
||||
assert(dt);
|
||||
strftime(str, sizeof(str), "%F; %T", dt);
|
||||
std::cout << std::endl << "Run Stop Time : " << str;
|
||||
if (dt != nullptr) {
|
||||
strftime(str, sizeof(str), "%F; %T", dt);
|
||||
std::cout << std::endl << "Run Stop Time : " << str;
|
||||
} else {
|
||||
std::cout << std::endl << "Run Stop Time : ??";
|
||||
}
|
||||
} else {
|
||||
std::cout << std::endl << "Run Stop Time : ???";
|
||||
}
|
||||
@@ -780,10 +840,14 @@ int dump_current_year()
|
||||
time_t rawtime;
|
||||
struct tm *timeinfo;
|
||||
char buffer[32];
|
||||
memset(buffer, '\0', sizeof(buffer));
|
||||
|
||||
time (&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
strftime(buffer, 32, "%Y", timeinfo);
|
||||
if (timeinfo != nullptr)
|
||||
strftime(buffer, 32, "%Y", timeinfo);
|
||||
else
|
||||
strncpy(buffer, "1900", sizeof(buffer));
|
||||
|
||||
return atoi(buffer);
|
||||
}
|
||||
@@ -911,7 +975,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
if (strcmp(argv[i+1], "lem") && strcmp(argv[i+1], "gps") && strcmp(argv[i+1], "ltf") &&
|
||||
strcmp(argv[i+1], "dolly") && strcmp(argv[i+1], "gpd") && strcmp(argv[i+1], "hifi") &&
|
||||
strcmp(argv[i+1], "flame")) {
|
||||
strcmp(argv[i+1], "flame") && strcmp(argv[i+1], "vms")) {
|
||||
std::cerr << std::endl << "**ERROR** found --instrument with unkown instrument name: '" << argv[i+1] << "'!" << std::endl;
|
||||
dump_header_syntax();
|
||||
return 1;
|
||||
@@ -940,13 +1004,14 @@ int main(int argc, char *argv[])
|
||||
// invoke the startup handler in order to get the default search paths to the data files
|
||||
// read startup file
|
||||
char startup_path_name[128];
|
||||
memset(startup_path_name, '\0', sizeof(startup_path_name));
|
||||
std::unique_ptr<TSAXParser> saxParser = std::make_unique<TSAXParser>();
|
||||
std::unique_ptr<PStartupHandler> startupHandler = std::make_unique<PStartupHandler>();
|
||||
if (!startupHandler->StartupFileFound()) {
|
||||
std::cerr << std::endl << ">> musrfit **WARNING** couldn't find " << startupHandler->GetStartupFilePath().Data();
|
||||
std::cerr << std::endl;
|
||||
} else {
|
||||
strcpy(startup_path_name, startupHandler->GetStartupFilePath().Data());
|
||||
strncpy(startup_path_name, startupHandler->GetStartupFilePath().Data(), sizeof(startup_path_name));
|
||||
saxParser->ConnectToHandler("PStartupHandler", startupHandler.get());
|
||||
//status = saxParser->ParseFile(startup_path_name);
|
||||
// parsing the file as above seems to lead to problems in certain environments;
|
||||
|
||||
90
src/external/BMWtools/BMWIntegrator.cpp
vendored
90
src/external/BMWtools/BMWIntegrator.cpp
vendored
@@ -26,6 +26,16 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* @file BMWIntegrator.cpp
|
||||
* @brief Implementation of various numerical integration classes for superconductivity calculations.
|
||||
*
|
||||
* This file implements integration methods for calculating superfluid density within the semi-classical
|
||||
* model for various superconducting order parameter symmetries using the Cuba library (Cuhre, Divonne, Suave algorithms).
|
||||
*
|
||||
* @author Bastian M. Wojek
|
||||
*/
|
||||
|
||||
#include "BMWIntegrator.h"
|
||||
|
||||
#include "cuba.h"
|
||||
@@ -42,10 +52,10 @@ std::vector<double> TPointPWaveGapIntegralCuhre::fPar;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Integrate the function using the Cuhre interface
|
||||
* @brief Integrate the function using the Cuhre interface.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - value of the integral
|
||||
* @param tag Selects which integrand to use: 0 for aa==bb component, otherwise cc component
|
||||
* @return Value of the integral
|
||||
*/
|
||||
double TPointPWaveGapIntegralCuhre::IntegrateFunc(int tag)
|
||||
{
|
||||
@@ -79,20 +89,20 @@ double TPointPWaveGapIntegralCuhre::IntegrateFunc(int tag)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the function value for the use with Cuhre---actual implementation of the function
|
||||
* for p-wave point, aa==bb component
|
||||
* @brief Calculate the function value for the use with Cuhre---actual implementation of the function
|
||||
* for p-wave point, aa==bb component.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - 0
|
||||
* @param ndim Number of dimensions of the integral (2 here)
|
||||
* @param x Point where the function should be evaluated: x = {E, z}
|
||||
* @param ncomp Number of components of the integrand (1 here)
|
||||
* @param f Function value (output)
|
||||
* @param userdata Additional user parameters (required by the interface, NULL here)
|
||||
* @return 0 on success
|
||||
*
|
||||
* \param ndim number of dimensions of the integral (2 here)
|
||||
* \param x point where the function should be evaluated
|
||||
* \param ncomp number of components of the integrand (1 here)
|
||||
* \param f function value
|
||||
* \param userdata additional user parameters (required by the interface, NULL here)
|
||||
* @note fPar = {twokBT, Delta(T), Ec, zc}
|
||||
*/
|
||||
int TPointPWaveGapIntegralCuhre::Integrand_aa(const int *ndim, const double x[],
|
||||
const int *ncomp, double f[], void *userdata) // x = {E, z}, fPar = {twokBT, Delta(T), Ec, zc}
|
||||
const int *ncomp, double f[], void *userdata)
|
||||
{
|
||||
double z = x[1]*fPar[3];
|
||||
double deltasq(pow(sqrt(1.0-z*z)*fPar[1],2.0));
|
||||
@@ -102,20 +112,20 @@ int TPointPWaveGapIntegralCuhre::Integrand_aa(const int *ndim, const double x[],
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the function value for the use with Cuhre---actual implementation of the function
|
||||
* for p-wave point, cc component
|
||||
* @brief Calculate the function value for the use with Cuhre---actual implementation of the function
|
||||
* for p-wave point, cc component.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - 0
|
||||
* @param ndim Number of dimensions of the integral (2 here)
|
||||
* @param x Point where the function should be evaluated: x = {E, z}
|
||||
* @param ncomp Number of components of the integrand (1 here)
|
||||
* @param f Function value (output)
|
||||
* @param userdata Additional user parameters (required by the interface, NULL here)
|
||||
* @return 0 on success
|
||||
*
|
||||
* \param ndim number of dimensions of the integral (2 here)
|
||||
* \param x point where the function should be evaluated
|
||||
* \param ncomp number of components of the integrand (1 here)
|
||||
* \param f function value
|
||||
* \param userdata additional user parameters (required by the interface, NULL here)
|
||||
* @note fPar = {twokBT, Delta(T), Ec, zc}
|
||||
*/
|
||||
int TPointPWaveGapIntegralCuhre::Integrand_cc(const int *ndim, const double x[],
|
||||
const int *ncomp, double f[], void *userdata) // x = {E, z}, fPar = {twokBT, Delta(T), Ec, zc}
|
||||
const int *ncomp, double f[], void *userdata)
|
||||
{
|
||||
double z = x[1]*fPar[3];
|
||||
double deltasq(pow(sqrt(1.0-z*z)*fPar[1],2.0));
|
||||
@@ -125,14 +135,14 @@ int TPointPWaveGapIntegralCuhre::Integrand_cc(const int *ndim, const double x[],
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
std::vector<double> TLinePWaveGapIntegralCuhre::fPar;
|
||||
std::vector<double> TLinePWaveGapIntegralCuhre::fPar; ///< Static parameter vector for line p-wave integrand
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Integrate the function using the Cuhre interface
|
||||
* @brief Integrate the function using the Cuhre interface for line p-wave symmetry.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - value of the integral
|
||||
* @param tag Selects which integrand to use: 0 for aa==bb component, otherwise cc component
|
||||
* @return Value of the integral
|
||||
*/
|
||||
double TLinePWaveGapIntegralCuhre::IntegrateFunc(int tag)
|
||||
{
|
||||
@@ -212,14 +222,13 @@ int TLinePWaveGapIntegralCuhre::Integrand_cc(const int *ndim, const double x[],
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
std::vector<double> TDWaveGapIntegralCuhre::fPar;
|
||||
std::vector<double> TDWaveGapIntegralCuhre::fPar; ///< Static parameter vector for d-wave integrand
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Integrate the function using the Cuhre interface
|
||||
* @brief Integrate the function using the Cuhre interface for d-wave symmetry.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - value of the integral
|
||||
* @return Value of the integral
|
||||
*/
|
||||
double TDWaveGapIntegralCuhre::IntegrateFunc()
|
||||
{
|
||||
@@ -247,19 +256,20 @@ double TDWaveGapIntegralCuhre::IntegrateFunc()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Calculate the function value for the use with Cuhre---actual implementation of the function
|
||||
* @brief Calculate the function value for the use with Cuhre---actual implementation of the function
|
||||
* for d-wave symmetry.
|
||||
*
|
||||
* <p><b>return:</b>
|
||||
* - 0
|
||||
* @param ndim Number of dimensions of the integral (2 here)
|
||||
* @param x Point where the function should be evaluated: x = {E, phi}
|
||||
* @param ncomp Number of components of the integrand (1 here)
|
||||
* @param f Function value (output)
|
||||
* @param userdata Additional user parameters (required by the interface, NULL here)
|
||||
* @return 0 on success
|
||||
*
|
||||
* \param ndim number of dimensions of the integral (2 here)
|
||||
* \param x point where the function should be evaluated
|
||||
* \param ncomp number of components of the integrand (1 here)
|
||||
* \param f function value
|
||||
* \param userdata additional user parameters (required by the interface, NULL here)
|
||||
* @note fPar = {twokBT, Delta(T), Ec, phic}
|
||||
*/
|
||||
int TDWaveGapIntegralCuhre::Integrand(const int *ndim, const double x[],
|
||||
const int *ncomp, double f[], void *userdata) // x = {E, phi}, fPar = {twokBT, Delta(T), Ec, phic}
|
||||
const int *ncomp, double f[], void *userdata)
|
||||
{
|
||||
double deltasq(TMath::Power(fPar[1]*TMath::Cos(2.0*x[1]*fPar[3]),2.0));
|
||||
f[0] = 1.0/TMath::Power(TMath::CosH(TMath::Sqrt(x[0]*x[0]*fPar[2]*fPar[2]+deltasq)/fPar[0]),2.0);
|
||||
|
||||
444
src/external/BMWtools/BMWIntegrator.h
vendored
444
src/external/BMWtools/BMWIntegrator.h
vendored
@@ -26,6 +26,17 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* @file BMWIntegrator.h
|
||||
* @brief Header file containing various numerical integration classes for superconductivity calculations.
|
||||
*
|
||||
* This file provides integration classes based on GNU Scientific Library (GSL) and the Cuba library
|
||||
* for calculating superfluid density within the semi-classical model for various superconducting
|
||||
* order parameter symmetries (s-wave, p-wave, d-wave, etc.) assuming cylindrical Fermi surfaces.
|
||||
*
|
||||
* @author Bastian M. Wojek
|
||||
*/
|
||||
|
||||
#ifndef _BMWIntegrator_H_
|
||||
#define _BMWIntegrator_H_
|
||||
|
||||
@@ -39,11 +50,15 @@
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Alternative base class for 1D integrations using the GNU Scientific Library integrator.
|
||||
* The difference to the other class is that here the integration parameters have to be supplied directly to the IntegrateFunc method.
|
||||
* Therefore, integrals with different parameters can be calculated in parallel (at least I hope so).
|
||||
* The function which should be integrated has to be implemented in a derived class.
|
||||
* Note: The purpose of this is to offer an easy-to-use interface---not the most efficient integration routine.
|
||||
* @class T2Integrator
|
||||
* @brief Alternative base class for 1D integrations using the GNU Scientific Library integrator.
|
||||
*
|
||||
* The difference to the other class is that here the integration parameters have to be supplied
|
||||
* directly to the IntegrateFunc method. Therefore, integrals with different parameters can be
|
||||
* calculated in parallel (at least I hope so). The function which should be integrated has to be
|
||||
* implemented in a derived class.
|
||||
*
|
||||
* @note The purpose of this is to offer an easy-to-use interface---not the most efficient integration routine.
|
||||
*/
|
||||
class T2Integrator {
|
||||
public:
|
||||
@@ -97,17 +112,20 @@ inline double T2Integrator::IntegrateFunc(double x1, double x2, const std::vecto
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Base class for 1D integrations using the GNU Scientific Library integrator.
|
||||
* The function which should be integrated has to be implemented in a derived class.
|
||||
* Note: The purpose of this is to offer an easy-to-use interface---not the most efficient integration routine.
|
||||
* @class TIntegrator
|
||||
* @brief Base class for 1D integrations using the GNU Scientific Library integrator.
|
||||
*
|
||||
* The function which should be integrated has to be implemented in a derived class.
|
||||
*
|
||||
* @note The purpose of this is to offer an easy-to-use interface---not the most efficient integration routine.
|
||||
*/
|
||||
class TIntegrator {
|
||||
public:
|
||||
TIntegrator();
|
||||
virtual ~TIntegrator();
|
||||
void SetParameters(const std::vector<double> &par) const { fPar=par; }
|
||||
virtual double FuncAtX(double) const = 0;
|
||||
double IntegrateFunc(double, double);
|
||||
void SetParameters(const std::vector<double> &par) const { fPar=par; } ///< Set integration parameters
|
||||
virtual double FuncAtX(double) const = 0; ///< Calculate integrand at point x (pure virtual)
|
||||
double IntegrateFunc(double, double); ///< Perform the integration
|
||||
|
||||
protected:
|
||||
mutable std::vector<double> fPar; ///< parameters of the integrand
|
||||
@@ -170,24 +188,28 @@ inline double TIntegrator::IntegrateFunc(double x1, double x2)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Base class for multidimensional Monte-Carlo integrations using the GNU Scientific Library integrator.
|
||||
* The function which should be integrated has to be implemented in a derived class.
|
||||
* Note: The purpose of this is to offer an easy-to-use interface---not the most efficient integration routine.
|
||||
* @class TMCIntegrator
|
||||
* @brief Base class for multidimensional Monte-Carlo integrations using the GNU Scientific Library integrator.
|
||||
*
|
||||
* The function which should be integrated has to be implemented in a derived class.
|
||||
* Uses the MISER algorithm of Press and Farrar.
|
||||
*
|
||||
* @note The purpose of this is to offer an easy-to-use interface---not the most efficient integration routine.
|
||||
*/
|
||||
class TMCIntegrator {
|
||||
public:
|
||||
TMCIntegrator();
|
||||
virtual ~TMCIntegrator();
|
||||
void SetParameters(const std::vector<double> &par) const { fPar=par; }
|
||||
virtual double FuncAtX(double *) const = 0;
|
||||
double IntegrateFunc(size_t, double *, double *);
|
||||
void SetParameters(const std::vector<double> &par) const { fPar=par; } ///< Set integration parameters
|
||||
virtual double FuncAtX(double *) const = 0; ///< Calculate integrand at point x (pure virtual)
|
||||
double IntegrateFunc(size_t, double *, double *); ///< Perform the multidimensional integration
|
||||
|
||||
protected:
|
||||
mutable std::vector<double> fPar; ///< parameters of the integrand
|
||||
|
||||
private:
|
||||
static double FuncAtXgsl(double *, size_t, void *);
|
||||
std::unique_ptr<ROOT::Math::GSLMCIntegrator> fMCIntegrator; ///< pointer to the GSL integrator
|
||||
std::unique_ptr<ROOT::Math::GSLMCIntegrator> fMCIntegrator; ///< pointer to the GSL Monte-Carlo integrator
|
||||
mutable double (*fFunc)(double *, size_t, void *); ///< pointer to the integrand function
|
||||
};
|
||||
|
||||
@@ -245,208 +267,238 @@ inline double TMCIntegrator::IntegrateFunc(size_t dim, double *x1, double *x2)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Two-dimensional integrator class for the efficient calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and a point p symmetry of the superconducting order parameter.
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
* @class TPointPWaveGapIntegralCuhre
|
||||
* @brief Two-dimensional integrator class for the efficient calculation of the superfluid density
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and a point p symmetry
|
||||
* of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
*/
|
||||
class TPointPWaveGapIntegralCuhre {
|
||||
public:
|
||||
TPointPWaveGapIntegralCuhre() : fNDim(2) {}
|
||||
~TPointPWaveGapIntegralCuhre() { fPar.clear(); }
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; }
|
||||
static int Integrand_aa(const int*, const double[], const int*, double[], void*);
|
||||
static int Integrand_cc(const int*, const double[], const int*, double[], void*);
|
||||
double IntegrateFunc(int tag);
|
||||
TPointPWaveGapIntegralCuhre() : fNDim(2) {} ///< Constructor
|
||||
~TPointPWaveGapIntegralCuhre() { fPar.clear(); } ///< Destructor
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; } ///< Set integration parameters
|
||||
static int Integrand_aa(const int*, const double[], const int*, double[], void*); ///< Integrand for aa==bb component
|
||||
static int Integrand_cc(const int*, const double[], const int*, double[], void*); ///< Integrand for cc component
|
||||
double IntegrateFunc(int tag); ///< Perform the integration (tag=0 for aa, tag!=0 for cc)
|
||||
|
||||
protected:
|
||||
static std::vector<double> fPar; ///< parameters of the integrand
|
||||
unsigned int fNDim; ///< dimension of the integral
|
||||
static std::vector<double> fPar; ///< parameters of the integrand (twokBT, Delta(T), Ec, zc)
|
||||
unsigned int fNDim; ///< dimension of the integral (2)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Two-dimensional integrator class for the efficient calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and a line p symmetry of the superconducting order parameter.
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
* @class TLinePWaveGapIntegralCuhre
|
||||
* @brief Two-dimensional integrator class for the efficient calculation of the superfluid density
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and a line p symmetry
|
||||
* of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
*/
|
||||
class TLinePWaveGapIntegralCuhre {
|
||||
public:
|
||||
TLinePWaveGapIntegralCuhre() : fNDim(2) {}
|
||||
~TLinePWaveGapIntegralCuhre() { fPar.clear(); }
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; }
|
||||
static int Integrand_aa(const int*, const double[], const int*, double[], void*);
|
||||
static int Integrand_cc(const int*, const double[], const int*, double[], void*);
|
||||
double IntegrateFunc(int tag);
|
||||
TLinePWaveGapIntegralCuhre() : fNDim(2) {} ///< Constructor
|
||||
~TLinePWaveGapIntegralCuhre() { fPar.clear(); } ///< Destructor
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; } ///< Set integration parameters
|
||||
static int Integrand_aa(const int*, const double[], const int*, double[], void*); ///< Integrand for aa==bb component
|
||||
static int Integrand_cc(const int*, const double[], const int*, double[], void*); ///< Integrand for cc component
|
||||
double IntegrateFunc(int tag); ///< Perform the integration (tag=0 for aa, tag!=0 for cc)
|
||||
|
||||
protected:
|
||||
static std::vector<double> fPar; ///< parameters of the integrand
|
||||
unsigned int fNDim; ///< dimension of the integral
|
||||
static std::vector<double> fPar; ///< parameters of the integrand (twokBT, Delta(T), Ec, zc)
|
||||
unsigned int fNDim; ///< dimension of the integral (2)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Two-dimensional integrator class for the efficient calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and a d_{x^2-y^2} symmetry of the superconducting order parameter.
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
* @class TDWaveGapIntegralCuhre
|
||||
* @brief Two-dimensional integrator class for the efficient calculation of the superfluid density
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and a d_{x^2-y^2} symmetry
|
||||
* of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
*/
|
||||
class TDWaveGapIntegralCuhre {
|
||||
public:
|
||||
TDWaveGapIntegralCuhre() : fNDim(2) {}
|
||||
~TDWaveGapIntegralCuhre() { fPar.clear(); }
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; }
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*);
|
||||
double IntegrateFunc();
|
||||
TDWaveGapIntegralCuhre() : fNDim(2) {} ///< Constructor
|
||||
~TDWaveGapIntegralCuhre() { fPar.clear(); } ///< Destructor
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; } ///< Set integration parameters
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*); ///< Integrand function
|
||||
double IntegrateFunc(); ///< Perform the integration
|
||||
|
||||
protected:
|
||||
static std::vector<double> fPar; ///< parameters of the integrand
|
||||
unsigned int fNDim; ///< dimension of the integral
|
||||
static std::vector<double> fPar; ///< parameters of the integrand (twokBT, Delta(T), Ec, phic)
|
||||
unsigned int fNDim; ///< dimension of the integral (2)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Two-dimensional integrator class for the efficient calculation of the superfluid density along the a-axis
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and a mixed d_{x^2-y^2} + s symmetry of the
|
||||
* superconducting order parameter (effectively: d_{x^2-y^2} with shifted nodes and a-b-anisotropy).
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
* @class TCosSqDWaveGapIntegralCuhre
|
||||
* @brief Two-dimensional integrator class for the efficient calculation of the superfluid density along the a-axis
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and a mixed d_{x^2-y^2} + s symmetry
|
||||
* of the superconducting order parameter (effectively: d_{x^2-y^2} with shifted nodes and a-b-anisotropy).
|
||||
*
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
*/
|
||||
class TCosSqDWaveGapIntegralCuhre {
|
||||
public:
|
||||
TCosSqDWaveGapIntegralCuhre() : fNDim(2) {}
|
||||
~TCosSqDWaveGapIntegralCuhre() { fPar.clear(); }
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; }
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*);
|
||||
double IntegrateFunc();
|
||||
TCosSqDWaveGapIntegralCuhre() : fNDim(2) {} ///< Constructor
|
||||
~TCosSqDWaveGapIntegralCuhre() { fPar.clear(); } ///< Destructor
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; } ///< Set integration parameters
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*); ///< Integrand function
|
||||
double IntegrateFunc(); ///< Perform the integration
|
||||
|
||||
protected:
|
||||
static std::vector<double> fPar; ///< parameters of the integrand
|
||||
unsigned int fNDim; ///< dimension of the integral
|
||||
static std::vector<double> fPar; ///< parameters of the integrand (twokBT, DeltaD(T), Ec, phic, DeltaS(T))
|
||||
unsigned int fNDim; ///< dimension of the integral (2)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Two-dimensional integrator class for the efficient calculation of the superfluid density along the b-axis
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and a mixed d_{x^2-y^2} + s symmetry of the
|
||||
* superconducting order parameter (effectively: d_{x^2-y^2} with shifted nodes and a-b-anisotropy).
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
* @class TSinSqDWaveGapIntegralCuhre
|
||||
* @brief Two-dimensional integrator class for the efficient calculation of the superfluid density along the b-axis
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and a mixed d_{x^2-y^2} + s symmetry
|
||||
* of the superconducting order parameter (effectively: d_{x^2-y^2} with shifted nodes and a-b-anisotropy).
|
||||
*
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
*/
|
||||
class TSinSqDWaveGapIntegralCuhre {
|
||||
public:
|
||||
TSinSqDWaveGapIntegralCuhre() : fNDim(2) {}
|
||||
~TSinSqDWaveGapIntegralCuhre() { fPar.clear(); }
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; }
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*);
|
||||
double IntegrateFunc();
|
||||
TSinSqDWaveGapIntegralCuhre() : fNDim(2) {} ///< Constructor
|
||||
~TSinSqDWaveGapIntegralCuhre() { fPar.clear(); } ///< Destructor
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; } ///< Set integration parameters
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*); ///< Integrand function
|
||||
double IntegrateFunc(); ///< Perform the integration
|
||||
|
||||
protected:
|
||||
static std::vector<double> fPar; ///< parameters of the integrand
|
||||
unsigned int fNDim; ///< dimension of the integral
|
||||
static std::vector<double> fPar; ///< parameters of the integrand (twokBT, DeltaD(T), Ec, phic, DeltaS(T))
|
||||
unsigned int fNDim; ///< dimension of the integral (2)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Two-dimensional integrator class for the efficient calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and an "anisotropic s-wave" symmetry of the superconducting order parameter.
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
* @class TAnSWaveGapIntegralCuhre
|
||||
* @brief Two-dimensional integrator class for the efficient calculation of the superfluid density
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and an "anisotropic s-wave"
|
||||
* symmetry of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
*/
|
||||
class TAnSWaveGapIntegralCuhre {
|
||||
public:
|
||||
TAnSWaveGapIntegralCuhre() : fNDim(2) {}
|
||||
~TAnSWaveGapIntegralCuhre() { fPar.clear(); }
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; }
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*);
|
||||
double IntegrateFunc();
|
||||
TAnSWaveGapIntegralCuhre() : fNDim(2) {} ///< Constructor
|
||||
~TAnSWaveGapIntegralCuhre() { fPar.clear(); } ///< Destructor
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; } ///< Set integration parameters
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*); ///< Integrand function
|
||||
double IntegrateFunc(); ///< Perform the integration
|
||||
|
||||
protected:
|
||||
static std::vector<double> fPar; ///< parameters of the integrand
|
||||
unsigned int fNDim; ///< dimension of the integral
|
||||
static std::vector<double> fPar; ///< parameters of the integrand (twokBT, Delta(T), a, Ec, phic)
|
||||
unsigned int fNDim; ///< dimension of the integral (2)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Two-dimensional integrator class for the efficient calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and an "anisotropic s-wave" symmetry of the superconducting order parameter.
|
||||
* The integration uses the Divonne algorithm of the Cuba library.
|
||||
* @class TAnSWaveGapIntegralDivonne
|
||||
* @brief Two-dimensional integrator class for the efficient calculation of the superfluid density
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and an "anisotropic s-wave"
|
||||
* symmetry of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the Divonne algorithm of the Cuba library.
|
||||
*/
|
||||
class TAnSWaveGapIntegralDivonne {
|
||||
public:
|
||||
TAnSWaveGapIntegralDivonne() : fNDim(2) {}
|
||||
~TAnSWaveGapIntegralDivonne() { fPar.clear(); }
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; }
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*);
|
||||
double IntegrateFunc();
|
||||
TAnSWaveGapIntegralDivonne() : fNDim(2) {} ///< Constructor
|
||||
~TAnSWaveGapIntegralDivonne() { fPar.clear(); } ///< Destructor
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; } ///< Set integration parameters
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*); ///< Integrand function
|
||||
double IntegrateFunc(); ///< Perform the integration
|
||||
|
||||
protected:
|
||||
static std::vector<double> fPar; ///< parameters of the integrand
|
||||
unsigned int fNDim; ///< dimension of the integral
|
||||
static std::vector<double> fPar; ///< parameters of the integrand (twokBT, Delta(T), a, Ec, phic)
|
||||
unsigned int fNDim; ///< dimension of the integral (2)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Two-dimensional integrator class for the efficient calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and an "anisotropic s-wave" symmetry of the superconducting order parameter.
|
||||
* The integration uses the Suave algorithm of the Cuba library.
|
||||
* @class TAnSWaveGapIntegralSuave
|
||||
* @brief Two-dimensional integrator class for the efficient calculation of the superfluid density
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and an "anisotropic s-wave"
|
||||
* symmetry of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the Suave algorithm of the Cuba library.
|
||||
*/
|
||||
class TAnSWaveGapIntegralSuave {
|
||||
public:
|
||||
TAnSWaveGapIntegralSuave() : fNDim(2) {}
|
||||
~TAnSWaveGapIntegralSuave() { fPar.clear(); }
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; }
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*);
|
||||
double IntegrateFunc();
|
||||
TAnSWaveGapIntegralSuave() : fNDim(2) {} ///< Constructor
|
||||
~TAnSWaveGapIntegralSuave() { fPar.clear(); } ///< Destructor
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; } ///< Set integration parameters
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*); ///< Integrand function
|
||||
double IntegrateFunc(); ///< Perform the integration
|
||||
|
||||
protected:
|
||||
static std::vector<double> fPar; ///< parameters of the integrand
|
||||
unsigned int fNDim; ///< dimension of the integral
|
||||
static std::vector<double> fPar; ///< parameters of the integrand (twokBT, Delta(T), a, Ec, phic)
|
||||
unsigned int fNDim; ///< dimension of the integral (2)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Two-dimensional integrator class for the efficient calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and an "non-monotonic d-wave" symmetry of the superconducting order parameter.
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
* @class TNonMonDWave1GapIntegralCuhre
|
||||
* @brief Two-dimensional integrator class for the efficient calculation of the superfluid density
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and a "non-monotonic d-wave"
|
||||
* symmetry of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
*/
|
||||
class TNonMonDWave1GapIntegralCuhre {
|
||||
public:
|
||||
TNonMonDWave1GapIntegralCuhre() : fNDim(2) {}
|
||||
~TNonMonDWave1GapIntegralCuhre() { fPar.clear(); }
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; }
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*);
|
||||
double IntegrateFunc();
|
||||
TNonMonDWave1GapIntegralCuhre() : fNDim(2) {} ///< Constructor
|
||||
~TNonMonDWave1GapIntegralCuhre() { fPar.clear(); } ///< Destructor
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; } ///< Set integration parameters
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*); ///< Integrand function
|
||||
double IntegrateFunc(); ///< Perform the integration
|
||||
|
||||
protected:
|
||||
static std::vector<double> fPar; ///< parameters of the integrand
|
||||
unsigned int fNDim; ///< dimension of the integral
|
||||
static std::vector<double> fPar; ///< parameters of the integrand (twokBT, Delta(T), a, Ec, phic)
|
||||
unsigned int fNDim; ///< dimension of the integral (2)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Two-dimensional integrator class for the efficient calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and an "non-monotonic d-wave" symmetry of the superconducting order parameter.
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
* @class TNonMonDWave2GapIntegralCuhre
|
||||
* @brief Two-dimensional integrator class for the efficient calculation of the superfluid density
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and a "non-monotonic d-wave"
|
||||
* symmetry of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the Cuhre algorithm of the Cuba library.
|
||||
*/
|
||||
class TNonMonDWave2GapIntegralCuhre {
|
||||
public:
|
||||
TNonMonDWave2GapIntegralCuhre() : fNDim(2) {}
|
||||
~TNonMonDWave2GapIntegralCuhre() { fPar.clear(); }
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; }
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*);
|
||||
double IntegrateFunc();
|
||||
TNonMonDWave2GapIntegralCuhre() : fNDim(2) {} ///< Constructor
|
||||
~TNonMonDWave2GapIntegralCuhre() { fPar.clear(); } ///< Destructor
|
||||
void SetParameters(const std::vector<double> &par) { fPar=par; } ///< Set integration parameters
|
||||
static int Integrand(const int*, const double[], const int*, double[], void*); ///< Integrand function
|
||||
double IntegrateFunc(); ///< Perform the integration
|
||||
|
||||
protected:
|
||||
static std::vector<double> fPar; ///< parameters of the integrand
|
||||
unsigned int fNDim; ///< dimension of the integral
|
||||
static std::vector<double> fPar; ///< parameters of the integrand (twokBT, Delta(T), a, Ec, phic)
|
||||
unsigned int fNDim; ///< dimension of the integral (2)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Test class for the 2D MC integration
|
||||
* Integral: x*y dx dy
|
||||
* @class T2DTest
|
||||
* @brief Test class for the 2D Monte-Carlo integration.
|
||||
*
|
||||
* Integral: x*y dx dy
|
||||
*/
|
||||
class T2DTest : public TMCIntegrator {
|
||||
public:
|
||||
T2DTest() {}
|
||||
~T2DTest() {}
|
||||
double FuncAtX(double *) const;
|
||||
T2DTest() {} ///< Constructor
|
||||
~T2DTest() {} ///< Destructor
|
||||
double FuncAtX(double *) const; ///< Calculate integrand x*y at point x
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -465,28 +517,34 @@ inline double T2DTest::FuncAtX(double *x) const
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Class for the 2D Monte-Carlo integration for the calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and a point p symmetry of the superconducting order parameter.
|
||||
* The integration uses the GSL integration routines.
|
||||
* @class TPointPWaveGapIntegral
|
||||
* @brief Class for the 2D Monte-Carlo integration for the calculation of the superfluid density
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and a point p symmetry
|
||||
* of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the GSL integration routines.
|
||||
*/
|
||||
class TPointPWaveGapIntegral : public TMCIntegrator {
|
||||
public:
|
||||
TPointPWaveGapIntegral() {}
|
||||
~TPointPWaveGapIntegral() {}
|
||||
double FuncAtX(double *) const;
|
||||
TPointPWaveGapIntegral() {} ///< Constructor
|
||||
~TPointPWaveGapIntegral() {} ///< Destructor
|
||||
double FuncAtX(double *) const; ///< Calculate integrand at point x
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Class for the 2D Monte-Carlo integration for the calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and a line p symmetry of the superconducting order parameter.
|
||||
* The integration uses the GSL integration routines.
|
||||
* @class TLinePWaveGapIntegral
|
||||
* @brief Class for the 2D Monte-Carlo integration for the calculation of the superfluid density
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and a line p symmetry
|
||||
* of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the GSL integration routines.
|
||||
*/
|
||||
class TLinePWaveGapIntegral : public TMCIntegrator {
|
||||
public:
|
||||
TLinePWaveGapIntegral() {}
|
||||
~TLinePWaveGapIntegral() {}
|
||||
double FuncAtX(double *) const;
|
||||
TLinePWaveGapIntegral() {} ///< Constructor
|
||||
~TLinePWaveGapIntegral() {} ///< Destructor
|
||||
double FuncAtX(double *) const; ///< Calculate integrand at point x
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -523,15 +581,18 @@ inline double TLinePWaveGapIntegral::FuncAtX(double *x) const // x = {E, theta},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Class for the 2D Monte-Carlo integration for the calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and a d_{x^2-y^2} symmetry of the superconducting order parameter.
|
||||
* The integration uses the GSL integration routines.
|
||||
* @class TDWaveGapIntegral
|
||||
* @brief Class for the 2D Monte-Carlo integration for the calculation of the superfluid density
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and a d_{x^2-y^2} symmetry
|
||||
* of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the GSL integration routines.
|
||||
*/
|
||||
class TDWaveGapIntegral : public TMCIntegrator {
|
||||
public:
|
||||
TDWaveGapIntegral() {}
|
||||
~TDWaveGapIntegral() {}
|
||||
double FuncAtX(double *) const;
|
||||
TDWaveGapIntegral() {} ///< Constructor
|
||||
~TDWaveGapIntegral() {} ///< Destructor
|
||||
double FuncAtX(double *) const; ///< Calculate integrand at point x
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -552,15 +613,18 @@ inline double TDWaveGapIntegral::FuncAtX(double *x) const // x = {E, phi}, fPar
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Class for the 2D Monte-Carlo integration for the calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and an "anisotropic s-wave" symmetry of the superconducting order parameter.
|
||||
* The integration uses the GSL integration routines.
|
||||
* @class TAnSWaveGapIntegral
|
||||
* @brief Class for the 2D Monte-Carlo integration for the calculation of the superfluid density
|
||||
* within the semi-classical model assuming a cylindrical Fermi surface and an "anisotropic s-wave"
|
||||
* symmetry of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the GSL integration routines.
|
||||
*/
|
||||
class TAnSWaveGapIntegral : public TMCIntegrator {
|
||||
public:
|
||||
TAnSWaveGapIntegral() {}
|
||||
~TAnSWaveGapIntegral() {}
|
||||
double FuncAtX(double *) const;
|
||||
TAnSWaveGapIntegral() {} ///< Constructor
|
||||
~TAnSWaveGapIntegral() {} ///< Destructor
|
||||
double FuncAtX(double *) const; ///< Calculate integrand at point x
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -581,16 +645,18 @@ inline double TAnSWaveGapIntegral::FuncAtX(double *x) const // x = {E, phi}, fPa
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Class for the 1D integration of j0(a*x)*exp(-b*x)
|
||||
* The integration uses the GSL integration routines.
|
||||
* @class TIntBesselJ0Exp
|
||||
* @brief Class for the 1D integration of j0(a*x)*exp(-b*x).
|
||||
*
|
||||
* The integration uses the GSL integration routines.
|
||||
*/
|
||||
class TIntBesselJ0Exp : public T2Integrator {
|
||||
public:
|
||||
TIntBesselJ0Exp() {}
|
||||
~TIntBesselJ0Exp() {}
|
||||
TIntBesselJ0Exp() {} ///< Constructor
|
||||
~TIntBesselJ0Exp() {} ///< Destructor
|
||||
|
||||
private:
|
||||
double FuncAtX(double, const std::vector<double>&) const;
|
||||
double FuncAtX(double, const std::vector<double>&) const; ///< Calculate integrand at point x
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -616,16 +682,18 @@ inline double TIntBesselJ0Exp::FuncAtX(double x, const std::vector<double> &par)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Class for the 1D integration of sin(a*x)*exp(-b*x*x)
|
||||
* The integration uses the GSL integration routines.
|
||||
* @class TIntSinGss
|
||||
* @brief Class for the 1D integration of sin(a*x)*exp(-b*x*x).
|
||||
*
|
||||
* The integration uses the GSL integration routines.
|
||||
*/
|
||||
class TIntSinGss : public T2Integrator {
|
||||
public:
|
||||
TIntSinGss() {}
|
||||
~TIntSinGss() {}
|
||||
TIntSinGss() {} ///< Constructor
|
||||
~TIntSinGss() {} ///< Destructor
|
||||
|
||||
private:
|
||||
double FuncAtX(double, const std::vector<double>&) const;
|
||||
double FuncAtX(double, const std::vector<double>&) const; ///< Calculate integrand at point x
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -644,18 +712,20 @@ inline double TIntSinGss::FuncAtX(double x, const std::vector<double> &par) cons
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Class for the 1D integration of the "DeRenzi Spin Glass Interpolation Integrand"
|
||||
* See Eq. (5) of R. De Renzi and S. Fanesi, Physica B 289-290, 209-212 (2000).
|
||||
* doi:10.1016/S0921-4526(00)00368-9
|
||||
* The integration uses the GSL integration routines.
|
||||
* @class TIntSGInterpolation
|
||||
* @brief Class for the 1D integration of the "DeRenzi Spin Glass Interpolation Integrand".
|
||||
*
|
||||
* See Eq. (5) of R. De Renzi and S. Fanesi, Physica B 289-290, 209-212 (2000).
|
||||
* doi:10.1016/S0921-4526(00)00368-9
|
||||
* The integration uses the GSL integration routines.
|
||||
*/
|
||||
class TIntSGInterpolation : public T2Integrator {
|
||||
public:
|
||||
TIntSGInterpolation() {}
|
||||
~TIntSGInterpolation() {}
|
||||
TIntSGInterpolation() {} ///< Constructor
|
||||
~TIntSGInterpolation() {} ///< Destructor
|
||||
|
||||
private:
|
||||
double FuncAtX(double, const std::vector<double>&) const;
|
||||
double FuncAtX(double, const std::vector<double>&) const; ///< Calculate integrand at point x
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -677,15 +747,17 @@ inline double TIntSGInterpolation::FuncAtX(double x, const std::vector<double> &
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Class for the 1D integration for the calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and an isotropic s-wave symmetry of the superconducting order parameter.
|
||||
* The integration uses the GSL integration routines.
|
||||
* @class TGapIntegral
|
||||
* @brief Class for the 1D integration for the calculation of the superfluid density within the semi-classical model
|
||||
* assuming a cylindrical Fermi surface and an isotropic s-wave symmetry of the superconducting order parameter.
|
||||
*
|
||||
* The integration uses the GSL integration routines.
|
||||
*/
|
||||
class TGapIntegral : public TIntegrator {
|
||||
public:
|
||||
TGapIntegral() {}
|
||||
~TGapIntegral() {}
|
||||
double FuncAtX(double) const; // variable: E
|
||||
TGapIntegral() {} ///< Constructor
|
||||
~TGapIntegral() {} ///< Destructor
|
||||
double FuncAtX(double) const; ///< Calculate integrand at energy E
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -704,16 +776,18 @@ inline double TGapIntegral::FuncAtX(double e) const
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Class for the 1D integration for the calculation of the uniaxial static Gauss-Kubo-Toyabe function
|
||||
* The integration uses the GSL integration routines.
|
||||
* @class TFirstUniaxialGssKTIntegral
|
||||
* @brief Class for the 1D integration for the calculation of the uniaxial static Gauss-Kubo-Toyabe function.
|
||||
*
|
||||
* The integration uses the GSL integration routines.
|
||||
*/
|
||||
class TFirstUniaxialGssKTIntegral : public T2Integrator {
|
||||
public:
|
||||
TFirstUniaxialGssKTIntegral() {}
|
||||
virtual ~TFirstUniaxialGssKTIntegral() {}
|
||||
TFirstUniaxialGssKTIntegral() {} ///< Constructor
|
||||
virtual ~TFirstUniaxialGssKTIntegral() {} ///< Destructor
|
||||
|
||||
private:
|
||||
virtual double FuncAtX(double, const std::vector<double>&) const; // variable: x
|
||||
virtual double FuncAtX(double, const std::vector<double>&) const; ///< Calculate integrand at point x
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -736,16 +810,18 @@ inline double TFirstUniaxialGssKTIntegral::FuncAtX(double x, const std::vector<d
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Class for the 1D integration for the calculation of the uniaxial static Gauss-Kubo-Toyabe function
|
||||
* The integration uses the GSL integration routines.
|
||||
* @class TSecondUniaxialGssKTIntegral
|
||||
* @brief Class for the 1D integration for the calculation of the uniaxial static Gauss-Kubo-Toyabe function.
|
||||
*
|
||||
* The integration uses the GSL integration routines.
|
||||
*/
|
||||
class TSecondUniaxialGssKTIntegral : public T2Integrator {
|
||||
public:
|
||||
TSecondUniaxialGssKTIntegral() {}
|
||||
virtual ~TSecondUniaxialGssKTIntegral() {}
|
||||
TSecondUniaxialGssKTIntegral() {} ///< Constructor
|
||||
virtual ~TSecondUniaxialGssKTIntegral() {} ///< Destructor
|
||||
|
||||
private:
|
||||
virtual double FuncAtX(double, const std::vector<double>&) const; // variable: x
|
||||
virtual double FuncAtX(double, const std::vector<double>&) const; ///< Calculate integrand at point x
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
100
src/external/BMWtools/BMWStartupHandler.cpp
vendored
100
src/external/BMWtools/BMWStartupHandler.cpp
vendored
@@ -11,7 +11,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter, Bastian M. Wojek *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter, Bastian M. Wojek *
|
||||
* *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -30,6 +30,16 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* @file BMWStartupHandler.cpp
|
||||
* @brief Implementation of the XML startup file handler for BMW tools.
|
||||
*
|
||||
* This file implements the BMWStartupHandler class which parses the BMW_startup.xml
|
||||
* configuration file using SAX2 XML parsing.
|
||||
*
|
||||
* @author Bastian M. Wojek (based on PStartupHandler.cpp by Andreas Suter)
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
@@ -39,22 +49,22 @@
|
||||
|
||||
ClassImpQ(BMWStartupHandler)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Constructor. Check if the BMW_startup.xml file is found in the local directory
|
||||
* @brief Constructor. Initializes all member variables to default values.
|
||||
*
|
||||
* The actual configuration will be loaded when the XML file is parsed.
|
||||
*/
|
||||
BMWStartupHandler::BMWStartupHandler() :
|
||||
fDebug(false), fLEM(false), fVortex(false), fLF(false), fDataPath(""), fDeltat(0.), fDeltaB(0.), fWisdomFile(""), fWisdomFileFloat(""), fNSteps(0), fGridSteps(0), fDeltatLF(0.), fNStepsLF(0)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Destructor
|
||||
* @brief Destructor. Cleans up allocated resources.
|
||||
*
|
||||
* Clears all internal vectors and maps.
|
||||
*/
|
||||
BMWStartupHandler::~BMWStartupHandler()
|
||||
{
|
||||
@@ -64,22 +74,23 @@ BMWStartupHandler::~BMWStartupHandler()
|
||||
fEnergies.clear();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// OnStartDocument
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called on start of the XML file reading. Initializes all necessary variables.
|
||||
* @brief Called on start of the XML file reading. Initializes all necessary variables.
|
||||
*
|
||||
* This method is automatically invoked by the SAX2 parser when parsing begins.
|
||||
*/
|
||||
void BMWStartupHandler::OnStartDocument()
|
||||
{
|
||||
fKey = eEmpty;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// OnEndDocument
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called on end of XML file reading.
|
||||
* @brief Called on end of XML file reading.
|
||||
*
|
||||
* This method is automatically invoked by the SAX2 parser when parsing completes.
|
||||
* It triggers validation and default value assignment.
|
||||
*/
|
||||
void BMWStartupHandler::OnEndDocument()
|
||||
{
|
||||
@@ -87,15 +98,13 @@ void BMWStartupHandler::OnEndDocument()
|
||||
CheckLists();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// OnStartElement
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when a XML start element is found. Filters out the needed elements
|
||||
* and sets a proper key.
|
||||
* @brief Called when an XML start element is found. Filters out the needed elements
|
||||
* and sets a proper key.
|
||||
*
|
||||
* \param str XML element name
|
||||
* \param attributes not used
|
||||
* @param str XML element name
|
||||
* @param attributes XML attributes (not used)
|
||||
*/
|
||||
void BMWStartupHandler::OnStartElement(const char *str, const TList *attributes)
|
||||
{
|
||||
@@ -132,27 +141,23 @@ void BMWStartupHandler::OnStartElement(const char *str, const TList *attributes)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// OnEndElement
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when a XML end element is found. Resets the handler key.
|
||||
* @brief Called when an XML end element is found. Resets the handler key.
|
||||
*
|
||||
* \param str not used
|
||||
* @param str XML element name (not used)
|
||||
*/
|
||||
void BMWStartupHandler::OnEndElement(const char *str)
|
||||
{
|
||||
fKey = eEmpty;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// OnCharacters
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Content of a given XML element. Filters out the data and feeds them to
|
||||
* the internal variables.
|
||||
* @brief Content of a given XML element. Filters out the data and feeds them to
|
||||
* the internal variables.
|
||||
*
|
||||
* \param str XML element string
|
||||
* @param str XML element content string
|
||||
*/
|
||||
void BMWStartupHandler::OnCharacters(const char *str)
|
||||
{
|
||||
@@ -221,26 +226,22 @@ void BMWStartupHandler::OnCharacters(const char *str)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// OnComment
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when a XML comment is found. Not used.
|
||||
* @brief Called when an XML comment is found. Not used.
|
||||
*
|
||||
* \param str not used.
|
||||
* @param str Comment string (not used)
|
||||
*/
|
||||
void BMWStartupHandler::OnComment(const char *str)
|
||||
{
|
||||
// nothing to be done for now
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// OnWarning
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when the XML parser emits a warning.
|
||||
* @brief Called when the XML parser emits a warning.
|
||||
*
|
||||
* \param str warning string
|
||||
* @param str Warning string
|
||||
*/
|
||||
void BMWStartupHandler::OnWarning(const char *str)
|
||||
{
|
||||
@@ -248,13 +249,11 @@ void BMWStartupHandler::OnWarning(const char *str)
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// OnError
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when the XML parser emits an error.
|
||||
* @brief Called when the XML parser emits an error.
|
||||
*
|
||||
* \param str error string
|
||||
* @param str Error string
|
||||
*/
|
||||
void BMWStartupHandler::OnError(const char *str)
|
||||
{
|
||||
@@ -262,13 +261,11 @@ void BMWStartupHandler::OnError(const char *str)
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// OnFatalError
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Called when the XML parser emits a fatal error.
|
||||
* @brief Called when the XML parser emits a fatal error.
|
||||
*
|
||||
* \param str fatal error string
|
||||
* @param str Fatal error string
|
||||
*/
|
||||
void BMWStartupHandler::OnFatalError(const char *str)
|
||||
{
|
||||
@@ -276,26 +273,25 @@ void BMWStartupHandler::OnFatalError(const char *str)
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// OnCdataBlock
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Not used.
|
||||
* @brief Called when an XML CDATA block is encountered. Not used.
|
||||
*
|
||||
* \param str not used
|
||||
* \param len not used
|
||||
* @param str CDATA content (not used)
|
||||
* @param len Length of CDATA (not used)
|
||||
*/
|
||||
void BMWStartupHandler::OnCdataBlock(const char *str, int len)
|
||||
{
|
||||
// nothing to be done for now
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// CheckList
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Check if the default lists are present and if not, feed them with some default settings
|
||||
* @brief Check if the default lists are present and if not, feed them with some default settings.
|
||||
*
|
||||
* This method validates all configuration parameters and assigns sensible defaults for any
|
||||
* parameters that were not specified in the XML file. It handles different modes (LF, LEM, Vortex)
|
||||
* and ensures that all required parameters are properly initialized.
|
||||
*/
|
||||
void BMWStartupHandler::CheckLists()
|
||||
{
|
||||
|
||||
91
src/external/BMWtools/BMWStartupHandler.h
vendored
91
src/external/BMWtools/BMWStartupHandler.h
vendored
@@ -11,7 +11,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter, Bastian M. Wojek *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter, Bastian M. Wojek *
|
||||
* *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -30,6 +30,16 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* @file BMWStartupHandler.h
|
||||
* @brief Header file for the XML startup file handler for BMW tools.
|
||||
*
|
||||
* This file contains the BMWStartupHandler class which parses the BMW_startup.xml
|
||||
* configuration file and provides default settings for the BMWtools plugin libraries.
|
||||
*
|
||||
* @author Bastian M. Wojek (based on PStartupHandler.h by Andreas Suter)
|
||||
*/
|
||||
|
||||
#ifndef _BMWSTARTUPHANDLER_H_
|
||||
#define _BMWSTARTUPHANDLER_H_
|
||||
|
||||
@@ -40,32 +50,36 @@
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* <p>Handles the XML musrfit startup file (BMW_startup.xml) where default settings for some plugin libraries are stored:
|
||||
* - TRIM.SP data file path and energies
|
||||
* - time and field resolutions for Fourier transforms
|
||||
* - paths to FFTW3 wisdom files (double and float)
|
||||
* - number of steps for one-dimensional theory functions (where needed)
|
||||
* - number of steps for two-dimensional grids when calculating spatial field distributions in vortex lattices
|
||||
* - time resolutions and lengths of Laplace transforms used in the calculation of LF-relaxation functions
|
||||
* - flag for debugging the information contained in the startup file
|
||||
* @class BMWStartupHandler
|
||||
* @brief Handles the XML musrfit startup file (BMW_startup.xml) where default settings for plugin libraries are stored.
|
||||
*
|
||||
* This class is a SAX2-based XML parser handler that reads and processes the BMW_startup.xml configuration file.
|
||||
* The configuration file contains default settings for:
|
||||
* - TRIM.SP data file path and energies (for low-energy muon implantation profiles)
|
||||
* - Time and field resolutions for Fourier transforms
|
||||
* - Paths to FFTW3 wisdom files (double and float precision)
|
||||
* - Number of steps for one-dimensional theory functions (where needed)
|
||||
* - Number of steps for two-dimensional grids when calculating spatial field distributions in vortex lattices
|
||||
* - Time resolutions and lengths of Laplace transforms used in the calculation of LF-relaxation functions
|
||||
* - Debug flag for verbose output of the information contained in the startup file
|
||||
*/
|
||||
class BMWStartupHandler : public TQObject {
|
||||
public:
|
||||
BMWStartupHandler();
|
||||
virtual ~BMWStartupHandler();
|
||||
|
||||
virtual void OnStartDocument(); // SLOT
|
||||
virtual void OnEndDocument(); // SLOT
|
||||
virtual void OnStartElement(const char*, const TList*); // SLOT
|
||||
virtual void OnEndElement(const char*); // SLOT
|
||||
virtual void OnCharacters(const char*); // SLOT
|
||||
virtual void OnComment(const char*); // SLOT
|
||||
virtual void OnWarning(const char*); // SLOT
|
||||
virtual void OnError(const char*); // SLOT
|
||||
virtual void OnFatalError(const char*); // SLOT
|
||||
virtual void OnCdataBlock(const char*, int); // SLOT
|
||||
virtual void OnStartDocument(); ///< Called when XML parsing begins
|
||||
virtual void OnEndDocument(); ///< Called when XML parsing ends
|
||||
virtual void OnStartElement(const char*, const TList*); ///< Called when an XML element starts
|
||||
virtual void OnEndElement(const char*); ///< Called when an XML element ends
|
||||
virtual void OnCharacters(const char*); ///< Called when XML character data is encountered
|
||||
virtual void OnComment(const char*); ///< Called when an XML comment is encountered
|
||||
virtual void OnWarning(const char*); ///< Called when the XML parser emits a warning
|
||||
virtual void OnError(const char*); ///< Called when the XML parser emits an error
|
||||
virtual void OnFatalError(const char*); ///< Called when the XML parser emits a fatal error
|
||||
virtual void OnCdataBlock(const char*, int); ///< Called when an XML CDATA block is encountered
|
||||
|
||||
virtual void CheckLists();
|
||||
virtual void CheckLists(); ///< Validates and sets default values for configuration parameters
|
||||
|
||||
virtual const std::string GetDataPath() const { return fDataPath; } ///< returns the path to TRIM.SP files
|
||||
virtual std::map<double, std::string> GetEnergies() const { return fEnergies; } ///< returns energies and file labels of available TRIM.SP files
|
||||
@@ -80,28 +94,31 @@ class BMWStartupHandler : public TQObject {
|
||||
virtual const bool GetDebug() const { return fDebug; } ///< true = debug the xml-entries
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Enumeration of XML element keywords used for parsing.
|
||||
*/
|
||||
enum EKeyWords {eEmpty, eComment, eDebug, eLEM, eVortex, eLF, eDataPath, eEnergyLabel, \
|
||||
eEnergy, eEnergyList, eDeltat, eDeltaB, eWisdomFile, eWisdomFileFloat, \
|
||||
eNSteps, eGridSteps, eDeltatLF, eNStepsLF};
|
||||
|
||||
EKeyWords fKey; ///< xml filter key
|
||||
EKeyWords fKey; ///< Current XML element being parsed
|
||||
|
||||
bool fDebug; ///< debug flag
|
||||
bool fLEM; ///< low-energy muSR flag
|
||||
bool fVortex; ///< vortex-lattice flag
|
||||
bool fLF; ///< longitudinal-field flag
|
||||
std::string fDataPath; ///< path to TRIM.SP files
|
||||
std::vector<std::string> fEnergyLabelList; ///< file labels of the TRIM.SP files
|
||||
std::vector<double> fEnergyList; ///< muon implantation energies of the TRIM.SP files
|
||||
std::map<double, std::string> fEnergies; ///< muon implantation energies and file labels of the TRIM.SP files
|
||||
double fDeltat; ///< time resolution of P(t) when using Fourier transforms
|
||||
double fDeltaB; ///< field resolution of p(B) when using Fourier transforms
|
||||
std::string fWisdomFile; ///< FFTW3 double-wisdom file
|
||||
std::string fWisdomFileFloat; ///< FFTW3 float-wisdom file
|
||||
unsigned int fNSteps; ///< number of steps in one-dimensional theory functions
|
||||
unsigned int fGridSteps; ///< number of steps in each direction when calculating two-dimensional spatial field distributions
|
||||
double fDeltatLF; ///< time resolution of P(t) when using Laplace transforms for the calculation of LF-relaxation functions
|
||||
unsigned int fNStepsLF; ///< length of the Laplace transforms for the calculation of LF-relaxation functions
|
||||
bool fDebug; ///< Debug flag for verbose output
|
||||
bool fLEM; ///< Low-energy muSR mode flag
|
||||
bool fVortex; ///< Vortex lattice calculations flag
|
||||
bool fLF; ///< Longitudinal field mode flag
|
||||
std::string fDataPath; ///< Path to TRIM.SP data files directory
|
||||
std::vector<std::string> fEnergyLabelList; ///< File name labels of the TRIM.SP files
|
||||
std::vector<double> fEnergyList; ///< Muon implantation energies in keV of the TRIM.SP files
|
||||
std::map<double, std::string> fEnergies; ///< Map of muon implantation energies (keV) to file labels
|
||||
double fDeltat; ///< Time resolution in microseconds for P(t) when using Fourier transforms
|
||||
double fDeltaB; ///< Field resolution in Gauss for p(B) when using Fourier transforms
|
||||
std::string fWisdomFile; ///< Path to FFTW3 double-precision wisdom file
|
||||
std::string fWisdomFileFloat; ///< Path to FFTW3 single-precision wisdom file
|
||||
unsigned int fNSteps; ///< Number of steps in one-dimensional theory functions
|
||||
unsigned int fGridSteps; ///< Number of grid points in each direction for 2D spatial field distributions
|
||||
double fDeltatLF; ///< Time resolution in microseconds for P(t) in LF Laplace transforms
|
||||
unsigned int fNStepsLF; ///< Length of the Laplace transforms for LF relaxation functions
|
||||
|
||||
ClassDef(BMWStartupHandler, 1)
|
||||
};
|
||||
|
||||
185
src/external/BMWtools/TTrimSPDataHandler.cpp
vendored
185
src/external/BMWtools/TTrimSPDataHandler.cpp
vendored
@@ -26,6 +26,16 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* @file TTrimSPDataHandler.cpp
|
||||
* @brief Implementation of the TRIM.SP muon implantation profile data handler.
|
||||
*
|
||||
* This file implements the TTrimSPData class which reads, stores, and manipulates
|
||||
* low-energy muon implantation profiles calculated by the TRIM.SP Monte Carlo code.
|
||||
*
|
||||
* @author Bastian M. Wojek
|
||||
*/
|
||||
|
||||
#include "TTrimSPDataHandler.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
@@ -36,9 +46,18 @@
|
||||
#include <memory>
|
||||
|
||||
//--------------------
|
||||
// Constructor of the TrimSPData class -- reading all available trim.SP-rge-files with a given name into std::vectors
|
||||
//--------------------
|
||||
|
||||
/**
|
||||
* @brief Constructor of the TTrimSPData class. Reads all available TRIM.SP .rge files.
|
||||
*
|
||||
* Reads muon implantation profiles from TRIM.SP .rge files for the specified energies.
|
||||
* The files are expected to be in the format output by TRIM.SP, with depth in Angstroms
|
||||
* and muon density n(z) as columns after the "PARTICLES" keyword.
|
||||
*
|
||||
* @param path Directory path containing the TRIM.SP .rge files
|
||||
* @param energies Map of muon energies (keV) to file name labels
|
||||
* @param debug Enable debug output (default: false)
|
||||
* @param highRes Use high-resolution (1 Angstrom) grid if non-zero (default: 0)
|
||||
*/
|
||||
TTrimSPData::TTrimSPData(const std::string &path, std::map<double, std::string> &energies, bool debug, unsigned int highRes) {
|
||||
|
||||
// sort the energies in ascending order - this might be useful for later applications (energy-interpolations etc.)
|
||||
@@ -114,11 +133,18 @@ TTrimSPData::TTrimSPData(const std::string &path, std::map<double, std::string>
|
||||
fEnergyIter = fEnergy.end();
|
||||
}
|
||||
|
||||
// Method checking if an implantation profile is available for a given energy
|
||||
// The behavior is the similar to the find-algorithm but more robust (tiny deviations in the energies are allowed).
|
||||
// If the given energy is found the methods sets the internal energy iterator to the element of the energy vector.
|
||||
// If it is not found the energy iterator will point to the end() of the energy vector.
|
||||
|
||||
//--------------------
|
||||
/**
|
||||
* @brief Find an implantation profile for a given energy.
|
||||
*
|
||||
* This method checks if an implantation profile is available for the specified energy.
|
||||
* The behavior is similar to std::find but more robust - tiny deviations in the energies
|
||||
* are allowed (tolerance of 0.05 keV). If the given energy is found, the method sets the
|
||||
* internal energy iterator to the corresponding element. If not found, the iterator will
|
||||
* point to end().
|
||||
*
|
||||
* @param e Muon energy in keV
|
||||
*/
|
||||
void TTrimSPData::FindEnergy(double e) const {
|
||||
for (fEnergyIter = fEnergy.begin(); fEnergyIter != fEnergy.end(); ++fEnergyIter) {
|
||||
if (fabs(*fEnergyIter - e) < 0.05)
|
||||
@@ -152,9 +178,15 @@ void TTrimSPData::UseHighResolution(double e) {
|
||||
}
|
||||
|
||||
//---------------------
|
||||
// Method returning z-vector calculated by trim.SP for given energy[keV]
|
||||
//---------------------
|
||||
|
||||
/**
|
||||
* @brief Get the depth vector calculated by TRIM.SP for a given energy.
|
||||
*
|
||||
* Returns the vector of depth points (in Angstroms) at which n(z) was calculated
|
||||
* by TRIM.SP for the specified energy.
|
||||
*
|
||||
* @param e Muon energy in keV
|
||||
* @return Vector of depth points in Angstroms. If energy not found, returns first available profile.
|
||||
*/
|
||||
std::vector<double> TTrimSPData::DataZ(double e) const {
|
||||
|
||||
FindEnergy(e);
|
||||
@@ -169,10 +201,15 @@ std::vector<double> TTrimSPData::DataZ(double e) const {
|
||||
}
|
||||
|
||||
//---------------------
|
||||
// Method returning actual n(z)-vector calculated by trim.SP and
|
||||
// potentially altered by the WeightLayers- or the Normalize-method for given energy[keV]
|
||||
//---------------------
|
||||
|
||||
/**
|
||||
* @brief Get the actual n(z) vector for a given energy.
|
||||
*
|
||||
* Returns the current n(z) implantation profile which may have been modified by
|
||||
* WeightLayers or Normalize methods.
|
||||
*
|
||||
* @param e Muon energy in keV
|
||||
* @return Vector of n(z) values. If energy not found, returns first available profile.
|
||||
*/
|
||||
std::vector<double> TTrimSPData::DataNZ(double e) const {
|
||||
|
||||
FindEnergy(e);
|
||||
@@ -188,9 +225,15 @@ std::vector<double> TTrimSPData::DataNZ(double e) const {
|
||||
}
|
||||
|
||||
//---------------------
|
||||
// Method returning original n(z)-vector calculated by trim.SP for given energy[keV]
|
||||
//---------------------
|
||||
|
||||
/**
|
||||
* @brief Get the original (unmodified) n(z) vector for a given energy.
|
||||
*
|
||||
* Returns the original n(z) implantation profile as read from the .rge file,
|
||||
* unaffected by any weighting or normalization operations.
|
||||
*
|
||||
* @param e Muon energy in keV
|
||||
* @return Vector of original n(z) values. If energy not found, returns first available profile.
|
||||
*/
|
||||
std::vector<double> TTrimSPData::OrigDataNZ(double e) const {
|
||||
|
||||
FindEnergy(e);
|
||||
@@ -220,10 +263,16 @@ double TTrimSPData::DataDZ(double e) const {
|
||||
}
|
||||
|
||||
//---------------------
|
||||
// Method returning fraction of muons implanted in the specified layer for a given energy[keV]
|
||||
// Parameters: Energy[keV], LayerNumber[1], Interfaces[nm]
|
||||
//---------------------
|
||||
|
||||
/**
|
||||
* @brief Calculate the fraction of muons implanted in a specified layer.
|
||||
*
|
||||
* Calculates the fraction of muons stopping in a given layer defined by interface positions.
|
||||
*
|
||||
* @param e Muon energy in keV
|
||||
* @param layno Layer number (starting from 1)
|
||||
* @param interface Vector of layer interface positions in nm
|
||||
* @return Fraction of muons in the specified layer (0.0 to 1.0). Returns 0.0 on error.
|
||||
*/
|
||||
double TTrimSPData::LayerFraction(double e, unsigned int layno, const std::vector<double>& interface) const {
|
||||
|
||||
if (layno < 1 && layno > (interface.size()+1)) {
|
||||
@@ -267,13 +316,20 @@ double TTrimSPData::LayerFraction(double e, unsigned int layno, const std::vecto
|
||||
}
|
||||
|
||||
//---------------------
|
||||
// Method putting different weight to different layers of your thin film
|
||||
// Parameters: Implantation Energy[keV], Interfaces[nm], Weights [0.0 <= w[i] <= 1.0]
|
||||
// Example: 25.0, (50, 100), (1.0, 0.33, 1.0)
|
||||
// at 25keV consider 3 layers, where the first ends after 50nm, the second after 100nm (these are NOT the layer thicknesses!!)
|
||||
// the first and last layers get the full n(z), where only one third of the muons in the second layer will be taken into account
|
||||
//---------------------
|
||||
|
||||
/**
|
||||
* @brief Apply different weights to different layers of a thin film sample.
|
||||
*
|
||||
* This method allows selective weighting of muon contributions from different layers,
|
||||
* useful for multi-layer samples where only certain layers are of interest.
|
||||
*
|
||||
* @param e Implantation energy in keV
|
||||
* @param interface Vector of layer interface positions in nm (cumulative depths, NOT layer thicknesses)
|
||||
* @param weight Vector of weights (0.0 to 1.0) for each layer
|
||||
*
|
||||
* @note Example: WeightLayers(25.0, {50, 100}, {1.0, 0.33, 1.0})
|
||||
* At 25 keV, consider 3 layers where the first ends at 50 nm and the second at 100 nm.
|
||||
* The first and last layers get full weight (1.0), while the second layer gets 0.33.
|
||||
*/
|
||||
void TTrimSPData::WeightLayers(double e, const std::vector<double>& interface, const std::vector<double>& weight) const {
|
||||
|
||||
if (weight.size()-interface.size()-1) {
|
||||
@@ -342,9 +398,16 @@ void TTrimSPData::WeightLayers(double e, const std::vector<double>& interface, c
|
||||
}
|
||||
|
||||
//---------------------
|
||||
// Method returning n(z) for given z[nm] and energy[keV]
|
||||
//---------------------
|
||||
|
||||
/**
|
||||
* @brief Get interpolated n(z) value at a specific depth and energy.
|
||||
*
|
||||
* Returns the muon density at a given depth using linear interpolation between
|
||||
* the discrete grid points from TRIM.SP.
|
||||
*
|
||||
* @param zz Depth in nanometers
|
||||
* @param e Muon energy in keV
|
||||
* @return Interpolated n(z) value. Returns 0.0 if z < 0 or beyond profile range.
|
||||
*/
|
||||
double TTrimSPData::GetNofZ(double zz, double e) const {
|
||||
|
||||
std::vector<double> z, nz;
|
||||
@@ -382,9 +445,14 @@ double TTrimSPData::GetNofZ(double zz, double e) const {
|
||||
}
|
||||
|
||||
//---------------------
|
||||
// Method normalizing the n(z)-vector calculated by trim.SP for a given energy[keV]
|
||||
//---------------------
|
||||
|
||||
/**
|
||||
* @brief Normalize the n(z) profile to unity integral.
|
||||
*
|
||||
* Normalizes the implantation profile so that the integral over all depths equals 1.
|
||||
* This is useful for converting absolute particle counts to probability densities.
|
||||
*
|
||||
* @param e Muon energy in keV
|
||||
*/
|
||||
void TTrimSPData::Normalize(double e) const {
|
||||
|
||||
FindEnergy(e);
|
||||
@@ -408,9 +476,12 @@ void TTrimSPData::Normalize(double e) const {
|
||||
}
|
||||
|
||||
//---------------------
|
||||
// Method telling you if the n(z)-vector calculated by trim.SP for a given energy [keV] has been normalized
|
||||
//---------------------
|
||||
|
||||
/**
|
||||
* @brief Check if the n(z) profile for a given energy has been normalized.
|
||||
*
|
||||
* @param e Muon energy in keV
|
||||
* @return true if the profile is normalized, false otherwise
|
||||
*/
|
||||
bool TTrimSPData::IsNormalized(double e) const {
|
||||
FindEnergy(e);
|
||||
|
||||
@@ -424,9 +495,15 @@ bool TTrimSPData::IsNormalized(double e) const {
|
||||
}
|
||||
|
||||
//---------------------
|
||||
// Calculate the mean range in (nm) for a given energy e
|
||||
//---------------------
|
||||
|
||||
/**
|
||||
* @brief Calculate the mean implantation depth for a given energy.
|
||||
*
|
||||
* Computes the first moment of the implantation profile, giving the average
|
||||
* stopping depth of muons.
|
||||
*
|
||||
* @param e Muon energy in keV
|
||||
* @return Mean implantation depth in nanometers. Returns -1.0 on error.
|
||||
*/
|
||||
double TTrimSPData::MeanRange(double e) const {
|
||||
FindEnergy(e);
|
||||
|
||||
@@ -447,9 +524,14 @@ double TTrimSPData::MeanRange(double e) const {
|
||||
}
|
||||
|
||||
//---------------------
|
||||
// Find the peak range in (nm) for a given energy e
|
||||
//---------------------
|
||||
|
||||
/**
|
||||
* @brief Find the peak position of the implantation profile.
|
||||
*
|
||||
* Locates the depth at which the implantation profile has its maximum value.
|
||||
*
|
||||
* @param e Muon energy in keV
|
||||
* @return Peak position in nanometers. Returns -1.0 on error.
|
||||
*/
|
||||
double TTrimSPData::PeakRange(double e) const {
|
||||
|
||||
FindEnergy(e);
|
||||
@@ -473,10 +555,17 @@ double TTrimSPData::PeakRange(double e) const {
|
||||
}
|
||||
|
||||
//---------------------
|
||||
// Convolve the n(z)-vector calculated by trim.SP for a given energy e [keV] with a gaussian exp(-z^2/(2*w^2))
|
||||
// No normalization is done!
|
||||
//---------------------
|
||||
|
||||
/**
|
||||
* @brief Convolve the implantation profile with a Gaussian.
|
||||
*
|
||||
* Convolves the n(z) profile with a Gaussian exp(-z²/(2w²)) to account for
|
||||
* additional broadening effects (e.g., straggling, surface roughness).
|
||||
*
|
||||
* @param w Gaussian width parameter in nanometers
|
||||
* @param e Muon energy in keV
|
||||
*
|
||||
* @note No normalization is performed after convolution.
|
||||
*/
|
||||
void TTrimSPData::ConvolveGss(double w, double e) const {
|
||||
if (!w)
|
||||
return;
|
||||
|
||||
73
src/external/BMWtools/TTrimSPDataHandler.h
vendored
73
src/external/BMWtools/TTrimSPDataHandler.h
vendored
@@ -26,6 +26,16 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* @file TTrimSPDataHandler.h
|
||||
* @brief Header file for handling TRIM.SP muon implantation profile data.
|
||||
*
|
||||
* This file contains the TTrimSPData class which reads, stores, and manipulates
|
||||
* low-energy muon implantation profiles calculated by the TRIM.SP Monte Carlo code.
|
||||
*
|
||||
* @author Bastian M. Wojek
|
||||
*/
|
||||
|
||||
#ifndef _TTrimSPDataHandler_H_
|
||||
#define _TTrimSPDataHandler_H_
|
||||
|
||||
@@ -34,7 +44,20 @@
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* <p>Class used to handle a set of low energy muon implantation profiles
|
||||
* @class TTrimSPData
|
||||
* @brief Class used to handle a set of low-energy muon implantation profiles.
|
||||
*
|
||||
* This class reads and manages muon implantation depth profiles calculated by the TRIM.SP
|
||||
* Monte Carlo code. It provides methods to access, manipulate, and analyze the implantation
|
||||
* profiles for different muon energies. The profiles describe the depth distribution n(z)
|
||||
* of implanted muons in a material.
|
||||
*
|
||||
* Key features:
|
||||
* - Read multiple TRIM.SP .rge files for different muon energies
|
||||
* - Interpolation of implantation profiles
|
||||
* - Layer weighting for multi-layer samples
|
||||
* - Normalization and convolution operations
|
||||
* - Calculation of mean and peak implantation depths
|
||||
*/
|
||||
class TTrimSPData {
|
||||
|
||||
@@ -49,34 +72,34 @@ public:
|
||||
fEnergy.clear();
|
||||
fDZ.clear();
|
||||
fIsNormalized.clear();
|
||||
}
|
||||
} ///< Destructor
|
||||
|
||||
std::vector<double> Energy() const {return fEnergy;}
|
||||
std::vector<double> DataZ(double) const;
|
||||
std::vector<double> DataNZ(double) const;
|
||||
std::vector<double> OrigDataNZ(double) const;
|
||||
double DataDZ(double) const;
|
||||
void UseHighResolution(double);
|
||||
void SetOriginal() {fOrigDataNZ = fDataNZ;}
|
||||
void WeightLayers(double, const std::vector<double>&, const std::vector<double>&) const;
|
||||
double LayerFraction(double, unsigned int, const std::vector<double>&) const;
|
||||
double GetNofZ(double, double) const;
|
||||
void Normalize(double) const;
|
||||
bool IsNormalized(double) const;
|
||||
void ConvolveGss(double, double) const;
|
||||
double MeanRange(double) const;
|
||||
double PeakRange(double) const;
|
||||
std::vector<double> Energy() const {return fEnergy;} ///< Get vector of available muon energies in keV
|
||||
std::vector<double> DataZ(double) const; ///< Get depth points (in Angstrom) for a given energy (keV)
|
||||
std::vector<double> DataNZ(double) const; ///< Get implantation profile n(z) for a given energy (keV)
|
||||
std::vector<double> OrigDataNZ(double) const; ///< Get original (unmodified) implantation profile for a given energy
|
||||
double DataDZ(double) const; ///< Get spatial resolution (Angstrom) for a given energy
|
||||
void UseHighResolution(double); ///< Switch to high-resolution (1 Angstrom) grid for given energy
|
||||
void SetOriginal() {fOrigDataNZ = fDataNZ;} ///< Store current profiles as new originals
|
||||
void WeightLayers(double, const std::vector<double>&, const std::vector<double>&) const; ///< Apply layer-dependent weights to profile
|
||||
double LayerFraction(double, unsigned int, const std::vector<double>&) const; ///< Calculate fraction of muons in specified layer
|
||||
double GetNofZ(double, double) const; ///< Get interpolated n(z) value at depth z (nm) for given energy (keV)
|
||||
void Normalize(double) const; ///< Normalize implantation profile to unity integral
|
||||
bool IsNormalized(double) const; ///< Check if profile for given energy is normalized
|
||||
void ConvolveGss(double, double) const; ///< Convolve profile with Gaussian of width w (nm)
|
||||
double MeanRange(double) const; ///< Calculate mean implantation depth (nm) for given energy
|
||||
double PeakRange(double) const; ///< Find peak position (nm) of implantation profile for given energy
|
||||
|
||||
private:
|
||||
void FindEnergy(double) const;
|
||||
void FindEnergy(double) const; ///< Internal method to locate energy in vector
|
||||
|
||||
std::vector<double> fEnergy; ///< vector holding all available muon energies
|
||||
std::vector<double> fDZ; ///< vector holding the spatial resolution of the TRIM.SP output for all energies
|
||||
std::vector< std::vector<double> > fDataZ; ///< discrete points in real space for which n(z) has been calculated for all energies
|
||||
mutable std::vector< std::vector<double> > fDataNZ; ///< n(z) for all energies
|
||||
std::vector< std::vector<double> > fOrigDataNZ; ///< original (unmodified) implantation profiles for all energies as read in from rge-files
|
||||
mutable std::vector<bool> fIsNormalized; ///< tag indicating if the implantation profiles are normalized (for each energy separately)
|
||||
mutable std::vector<double>::const_iterator fEnergyIter; ///< iterator traversing the vector of available energies
|
||||
std::vector<double> fEnergy; ///< Vector holding all available muon energies in keV
|
||||
std::vector<double> fDZ; ///< Vector holding the spatial resolution (Angstrom) of the TRIM.SP output for all energies
|
||||
std::vector< std::vector<double> > fDataZ; ///< Discrete depth points in Angstrom for which n(z) has been calculated for all energies
|
||||
mutable std::vector< std::vector<double> > fDataNZ; ///< Muon density n(z) for all energies (may be modified by weighting/normalization)
|
||||
std::vector< std::vector<double> > fOrigDataNZ; ///< Original (unmodified) implantation profiles for all energies as read from .rge files
|
||||
mutable std::vector<bool> fIsNormalized; ///< Flag indicating if the implantation profiles are normalized (for each energy separately)
|
||||
mutable std::vector<double>::const_iterator fEnergyIter; ///< Iterator for traversing the vector of available energies
|
||||
};
|
||||
|
||||
#endif // _TTrimSPDataHandler_H_
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2013-2025 by Andreas Suter *
|
||||
* Copyright (C) 2013-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2013-2025 by Andreas Suter *
|
||||
* Copyright (C) 2013-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2025 by Andreas Suter *
|
||||
* Copyright (C) 2009-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2013-2025 by Andreas Suter *
|
||||
* Copyright (C) 2013-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2013-2025 by Andreas Suter *
|
||||
* Copyright (C) 2013-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2025 by Andreas Suter *
|
||||
* Copyright (C) 2009-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/LF_GL/PGKT_LF.cpp
vendored
2
src/external/LF_GL/PGKT_LF.cpp
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/LF_GL/PGKT_LF.h
vendored
2
src/external/LF_GL/PGKT_LF.h
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/LF_GL/PLGKT_LF.cpp
vendored
2
src/external/LF_GL/PLGKT_LF.cpp
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/LF_GL/PLGKT_LF.h
vendored
2
src/external/LF_GL/PLGKT_LF.h
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2011-2025 by Andreas Suter *
|
||||
* Copyright (C) 2011-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2011-2025 by Andreas Suter *
|
||||
* Copyright (C) 2011-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2011-2025 by Andreas Suter *
|
||||
* Copyright (C) 2011-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/MagProximity/PMagProximity.h
vendored
2
src/external/MagProximity/PMagProximity.h
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2011-2025 by Andreas Suter *
|
||||
* Copyright (C) 2011-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2011-2025 by Andreas Suter *
|
||||
* Copyright (C) 2011-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2025 by Andreas Suter *
|
||||
* Copyright (C) 2009-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2011-2025 by Andreas Suter *
|
||||
* Copyright (C) 2011-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
contains meta file infromation of the needed trim.sp files.
|
||||
</comment>
|
||||
<trim_sp>
|
||||
<data_path>/afs/psi.ch/project/nemu/analysis/2010/EuS-Co/trimsp2</data_path>
|
||||
<data_path>/psi.ch/group/lmu/public/analysis/lem/2010/EuS-Co/trimsp2</data_path>
|
||||
<rge_fln_pre>EuS-Co_E</rge_fln_pre>
|
||||
<energy_list>
|
||||
<energy>5030</energy>
|
||||
|
||||
2
src/external/MusrRoot/TMusrRunHeader.cpp
vendored
2
src/external/MusrRoot/TMusrRunHeader.cpp
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/MusrRoot/TMusrRunHeader.h
vendored
2
src/external/MusrRoot/TMusrRunHeader.h
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/Nonlocal/PNL_PippardFitter.cpp
vendored
2
src/external/Nonlocal/PNL_PippardFitter.cpp
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2025 by Andreas Suter *
|
||||
* Copyright (C) 2009-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/Nonlocal/PNL_PippardFitter.h
vendored
2
src/external/Nonlocal/PNL_PippardFitter.h
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2025 by Andreas Suter *
|
||||
* Copyright (C) 2009-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2025 by Andreas Suter *
|
||||
* Copyright (C) 2009-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/Nonlocal/PNL_StartupHandler.cpp
vendored
2
src/external/Nonlocal/PNL_StartupHandler.cpp
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2025 by Andreas Suter *
|
||||
* Copyright (C) 2009-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/Nonlocal/PNL_StartupHandler.h
vendored
2
src/external/Nonlocal/PNL_StartupHandler.h
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2025 by Andreas Suter *
|
||||
* Copyright (C) 2009-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2025 by Andreas Suter *
|
||||
* Copyright (C) 2009-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
23
src/external/Nonlocal/prog/CMakeLists.txt
vendored
23
src/external/Nonlocal/prog/CMakeLists.txt
vendored
@@ -2,6 +2,11 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
# cmake: use BoostConfig.cmake instead of FindBoost
|
||||
if (CMAKE_VERSION GREATER_EQUAL "3.3")
|
||||
cmake_policy(SET CMP0167 NEW)
|
||||
endif()
|
||||
|
||||
project(dump_nonlocal_field VERSION 1.0.0 LANGUAGES C CXX)
|
||||
|
||||
#--- check for git ------------------------------------------------------------
|
||||
@@ -22,11 +27,19 @@ if (ROOT_mathmore_FOUND)
|
||||
endif (ROOT_mathmore_FOUND)
|
||||
|
||||
#--- check for boost ----------------------------------------------------------
|
||||
find_package(Boost REQUIRED
|
||||
COMPONENTS
|
||||
system
|
||||
filesystem
|
||||
)
|
||||
find_package(Boost QUIET)
|
||||
if (Boost_VERSION VERSION_GREATER_EQUAL "1.89")
|
||||
find_package(Boost REQUIRED
|
||||
COMPONENTS
|
||||
filesystem
|
||||
)
|
||||
else (Boost_VERSION VERSION_GREATER_EQUAL "1.89")
|
||||
find_package(Boost REQUIRED
|
||||
COMPONENTS
|
||||
system
|
||||
filesystem
|
||||
)
|
||||
endif (Boost_VERSION VERSION_GREATER_EQUAL "1.89")
|
||||
message(STATUS "Boost libs: ${Boost_LIBRARIES}")
|
||||
|
||||
#--- check for fftw3 ----------------------------------------------------------
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2025 by Andreas Suter *
|
||||
* Copyright (C) 2009-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008-2025 by Bastian M. Wojek, Andreas Suter *
|
||||
* Copyright (C) 2008-2026 by Bastian M. Wojek, Andreas Suter *
|
||||
* *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/libGbGLF/PGbGLF.cpp
vendored
2
src/external/libGbGLF/PGbGLF.cpp
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/libGbGLF/PGbGLF.h
vendored
2
src/external/libGbGLF/PGbGLF.h
vendored
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007-2025 by Andreas Suter *
|
||||
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
2
src/external/libGbGLF/PGbGLFLinkDef.h
vendored
2
src/external/libGbGLF/PGbGLFLinkDef.h
vendored
@@ -7,7 +7,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2016-2025 by Andreas Suter *
|
||||
* Copyright (C) 2016-2026 by Andreas Suter *
|
||||
* *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2013-2025 by Andreas Suter *
|
||||
* Copyright (C) 2013-2026 by Andreas Suter *
|
||||
* andreas.suter@psi.ch *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user