add HDF4/HDF5 example programs.
This commit is contained in:
69
src/external/nexus/README.Cygwin
vendored
69
src/external/nexus/README.Cygwin
vendored
@@ -1,69 +0,0 @@
|
|||||||
2011/04/13 -- BMW
|
|
||||||
|
|
||||||
Under Cygwin of all the required libraries for NeXus only HDF5 is available.
|
|
||||||
The packages <hdf5> and <libhdf5-devel> can be installed through the Cygwin setup.
|
|
||||||
One should also make sure that <bison>, <flex> and a package containing "/usr/lib/librpc.a" (e.g. <sunrpc> = 4.0-3) are installed.
|
|
||||||
|
|
||||||
All other libraries have to be built from the sources:
|
|
||||||
|
|
||||||
* JPEG-6b
|
|
||||||
URL: http://www.hdfgroup.org/ftp/lib-external/jpeg/src/jpegsrc.v6b.tar.gz
|
|
||||||
Configure options: --prefix=/usr/local --enable-static
|
|
||||||
|
|
||||||
* MXML 2.5
|
|
||||||
URL: http://ftp.easysw.com/pub/mxml/2.5/mxml-2.5.tar.gz
|
|
||||||
Configure options: --prefix=/usr/local --enable-static
|
|
||||||
|
|
||||||
* HDF 4.2.5
|
|
||||||
URL: http://www.hdfgroup.org/ftp/HDF/HDF_Current/src/hdf-4.2.5.tar.gz
|
|
||||||
Configure options: --prefix=/usr/local --enable-static --disable-fortran --with-jpeg=/usr/local
|
|
||||||
|
|
||||||
* NeXus 4.2.1
|
|
||||||
URL: http://download.nexusformat.org/kits/nexus-4.2.1.tar.gz
|
|
||||||
Configure options: --prefix=/usr/local --with-hdf4=/usr/local --with-hdf5=/usr --with-xml=/usr/local
|
|
||||||
|
|
||||||
The version numbers and source-code locations might of course change with time but should be easily adjustable.
|
|
||||||
|
|
||||||
If one is confident enough that all requirements to build the above packages are fullfilled, one could also try to run the following lines as a script.
|
|
||||||
However, there is absolutely no warranty that it works.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
cd
|
|
||||||
mkdir nexus
|
|
||||||
cd nexus
|
|
||||||
curl http://www.hdfgroup.org/ftp/lib-external/jpeg/src/jpegsrc.v6b.tar.gz -G | tar xz
|
|
||||||
cd jpeg-6b
|
|
||||||
./configure --prefix=/usr/local --enable-static
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
cd ..
|
|
||||||
curl http://ftp.easysw.com/pub/mxml/2.5/mxml-2.5.tar.gz -G | tar xz
|
|
||||||
cd mxml-2.5
|
|
||||||
./configure --prefix=/usr/local --enable-static
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
cd ..
|
|
||||||
curl http://www.hdfgroup.org/ftp/HDF/HDF_Current/src/hdf-4.2.5.tar.gz -G | tar xz
|
|
||||||
cd hdf-4.2.5
|
|
||||||
./configure --prefix=/usr/local --enable-static --disable-fortran --with-jpeg=/usr/local
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
cd ..
|
|
||||||
curl http://download.nexusformat.org/kits/nexus-4.2.1.tar.gz -G | tar xz
|
|
||||||
./configure --prefix=/usr/local --with-hdf4=/usr/local --with-hdf5=/usr --with-xml=/usr/local
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
In order to obtain NeXus support in musrfit after installing the above libraries, musrfit has to be configured with the options
|
|
||||||
"--enable-static --enable-NeXus"
|
|
||||||
|
|
||||||
Further information on how to set up musrfit under Cygwin can be found here:
|
|
||||||
https://intranet.psi.ch/MUSR/MusrFitSetup#A_4_MS_Windows
|
|
||||||
http://lmu.web.psi.ch/facilities/software/musrfit/user/intranet.psi.ch/MUSR/MusrFitSetup.html#A_4_MS_Windows
|
|
||||||
|
|
||||||
EOF
|
|
||||||
149
src/external/nexus/examples/hdf4/CMakeLists.txt
vendored
Normal file
149
src/external/nexus/examples/hdf4/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
# - h4nexus
|
||||||
|
cmake_minimum_required(VERSION 3.26)
|
||||||
|
|
||||||
|
project(h4nexus VERSION 0.1.0 LANGUAGES CXX)
|
||||||
|
|
||||||
|
#--- set C++ standard ---------------------------------------------------------
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
#--- set a default build type if none was specified ---------------------------
|
||||||
|
set(default_build_type "Release")
|
||||||
|
|
||||||
|
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
|
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
|
||||||
|
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE
|
||||||
|
STRING "Choose the type of build." FORCE)
|
||||||
|
# Set the possible values of build type for cmake-gui
|
||||||
|
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||||
|
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
#--- check for pkg-config -----------------------------------------------------
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
|
#--- check for git ------------------------------------------------------------
|
||||||
|
find_package(Git 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 ()
|
||||||
|
|
||||||
|
include_directories(${HDF4_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
#--- check for HDF5 -----------------------------------------------------------
|
||||||
|
find_package(HDF5 REQUIRED COMPONENTS CXX)
|
||||||
|
if(NOT HDF5_FOUND)
|
||||||
|
message(FATAL_ERROR "HDF5 C++ library not found")
|
||||||
|
endif()
|
||||||
|
include_directories(${HDF5_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
#--- check for ROOT -----------------------------------------------------------
|
||||||
|
find_package(ROOT 6.36 REQUIRED COMPONENTS Minuit2)
|
||||||
|
if (ROOT_miniut2_FOUND)
|
||||||
|
execute_process(COMMAND root-config --bindir OUTPUT_VARIABLE ROOT_BINDIR)
|
||||||
|
string(STRIP ${ROOT_BINDIR} ROOT_BINDIR)
|
||||||
|
execute_process(COMMAND root-config --version OUTPUT_VARIABLE ROOT_VERSION)
|
||||||
|
string(STRIP ${ROOT_VERSION} ROOT_VERSION)
|
||||||
|
message("-- Found ROOT: ${ROOT_BINDIR} (found version: ${ROOT_VERSION})")
|
||||||
|
#---Define useful ROOT functions and macros (e.g. ROOT_GENERATE_DICTIONARY)
|
||||||
|
include(${ROOT_USE_FILE})
|
||||||
|
endif (ROOT_miniut2_FOUND)
|
||||||
|
|
||||||
|
#--- all checks done -> feed config.h -----------------------------------------
|
||||||
|
set(HAVE_CONFIG_H 1 CACHE INTERNAL "config.h is available")
|
||||||
|
configure_file(${CMAKE_SOURCE_DIR}/cmake/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
|
||||||
|
#--- check if project source is a git repo ------------------------------------
|
||||||
|
if (EXISTS "${CMAKE_SOURCE_DIR}/.git/HEAD")
|
||||||
|
message(STATUS "is a git repo")
|
||||||
|
set(IS_GIT_REPO 1)
|
||||||
|
else ()
|
||||||
|
message(STATUS "is NOT a git repo")
|
||||||
|
set(IS_GIT_REPO 0)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
#--- start create git-revision.h ----------------------------------------------
|
||||||
|
if (IS_GIT_REPO)
|
||||||
|
execute_process(COMMAND sh ${CMAKE_SOURCE_DIR}/git_revision.sh ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
|
set(HAVE_GIT_REV_H "-DHAVE_GIT_REV_H")
|
||||||
|
set(GIT_REV_H "git-revision.h")
|
||||||
|
else (IS_GIT_REPO)
|
||||||
|
set(HAVE_GIT_REV_H "")
|
||||||
|
set(GIT_REV_H "")
|
||||||
|
endif (IS_GIT_REPO)
|
||||||
|
|
||||||
|
#--- end create git-revision.h ------------------------------------------------
|
||||||
|
|
||||||
|
#--- write summary of the installation
|
||||||
|
cmake_host_system_information(RESULT PROCESSOR QUERY PROCESSOR_DESCRIPTION)
|
||||||
|
|
||||||
|
message("")
|
||||||
|
message("|-----------------------------------------------------------------------|")
|
||||||
|
message("| |")
|
||||||
|
message("| Summary |")
|
||||||
|
message("| |")
|
||||||
|
message("|-----------------------------------------------------------------------|")
|
||||||
|
message("")
|
||||||
|
message(" System: ${CMAKE_HOST_SYSTEM_NAME} ${CMAKE_SYSTEM_PROCESSOR} - ${CMAKE_HOST_SYSTEM_VERSION}")
|
||||||
|
message(" Processor: ${PROCESSOR} (${CMAKE_SYSTEM_PROCESSOR})")
|
||||||
|
message(" ----------")
|
||||||
|
message("")
|
||||||
|
message(" h4nexus Version: ${h4nexus_VERSION}")
|
||||||
|
message(" ----------------")
|
||||||
|
message("")
|
||||||
|
message(" Build Type: ${CMAKE_BUILD_TYPE}")
|
||||||
|
message(" -----------")
|
||||||
|
message("")
|
||||||
|
message(" Requirements:")
|
||||||
|
message(" -------------")
|
||||||
|
message("")
|
||||||
|
message(" HDF4 found in ${HDF4_INCLUDE_DIRS}")
|
||||||
|
message(" ROOT found in ${ROOT_INCLUDE_DIRS}, Version: ${ROOT_VERSION}")
|
||||||
|
message("")
|
||||||
|
message(" Installation directories:")
|
||||||
|
message(" -------------------------")
|
||||||
|
message("")
|
||||||
|
message(" Programs : ${CMAKE_INSTALL_PREFIX}/bin")
|
||||||
|
message("")
|
||||||
|
message("-------------------------------------------------------------------------")
|
||||||
|
message("")
|
||||||
|
|
||||||
|
#--- h4nexus executable -------------------------------------------------------
|
||||||
|
add_executable(h4nexus
|
||||||
|
../../PNeXus.cpp
|
||||||
|
main.cpp)
|
||||||
|
target_compile_options(h4nexus BEFORE PRIVATE "-DHAVE_HDF4 -DHAVE_CONFIG_H" ${HAVE_GIT_REV_H})
|
||||||
|
target_include_directories(h4nexus
|
||||||
|
BEFORE PRIVATE
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/build>
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/../..>
|
||||||
|
$<BUILD_INTERFACE:${ROOT_INCLUDE_DIRS}>
|
||||||
|
)
|
||||||
|
target_link_libraries(h4nexus ${HDF4_LIBRARIES} ${HDF5_LIBRARIES} ${ROOT_LIBRARIES})
|
||||||
7
src/external/nexus/examples/hdf4/cmake/config.h.in
vendored
Normal file
7
src/external/nexus/examples/hdf4/cmake/config.h.in
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* config.h.in. Generated from CMakeLists.txt */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <config.h> file. */
|
||||||
|
#cmakedefine HAVE_CONFIG_H @HAVE_CONFIG_H@
|
||||||
|
|
||||||
|
/* h4nexus version */
|
||||||
|
#define H4NEXUS_VERSION "@h4nexus_VERSION@"
|
||||||
165
src/external/nexus/examples/hdf4/docu/README.md
vendored
Normal file
165
src/external/nexus/examples/hdf4/docu/README.md
vendored
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
# h4nexus - handle muSR-NeXus files via HDF4 only
|
||||||
|
|
||||||
|
## Contents
|
||||||
|
|
||||||
|
Tests and classes to handle muSR-NeXus files directly via the HDF4 C API.
|
||||||
|
|
||||||
|
This project provides the same API as h5nexus but uses HDF4 instead of HDF5 for handling NeXus files.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Read and write NeXus HDF4 files** with a clean C++ API
|
||||||
|
- **Case-insensitive path lookup** for datasets and groups
|
||||||
|
- **Type-safe data handling** using template classes
|
||||||
|
- **Dead time correction calculation** for muon detector data using ROOT Minuit2
|
||||||
|
- **Compatible API with h5nexus** for easy migration
|
||||||
|
|
||||||
|
## Key Classes
|
||||||
|
|
||||||
|
- `nxH4::PNeXus` - Main class for reading/writing NeXus HDF4 files
|
||||||
|
- `nxH4::PNXdata<T>` - Template class for storing dataset content with attributes
|
||||||
|
- `nxH4::PNeXusDeadTime` - Dead time correction calculator for muon detector data
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- CMake >= 3.26
|
||||||
|
- C++17 compatible compiler
|
||||||
|
- HDF4 library (libhdf4-dev or hdf-devel)
|
||||||
|
- ROOT >= 6.36 with Minuit2 component
|
||||||
|
- pkg-config
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
|
This will install:
|
||||||
|
- Library: `libh4nexus.so` in `${CMAKE_INSTALL_PREFIX}/lib`
|
||||||
|
- Executable: `h4nexus` in `${CMAKE_INSTALL_PREFIX}/bin`
|
||||||
|
- Header: `PNeXus.h` in `${CMAKE_INSTALL_PREFIX}/include/h4nexus`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Command Line
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Display help
|
||||||
|
h4nexus --help
|
||||||
|
|
||||||
|
# Read and display a NeXus HDF4 file
|
||||||
|
h4nexus --fn input.nxs
|
||||||
|
|
||||||
|
# Read with debug output
|
||||||
|
h4nexus --fn input.nxs --debug
|
||||||
|
|
||||||
|
# Calculate dead time corrections
|
||||||
|
h4nexus --fn input.nxs --dead_time_estimate
|
||||||
|
|
||||||
|
# Write output file
|
||||||
|
h4nexus --fn input.nxs --out output.nxs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Programmatic Usage
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <h4nexus/PNeXus.h>
|
||||||
|
|
||||||
|
// Read a NeXus file
|
||||||
|
nxH4::PNeXus nexus("data.nxs");
|
||||||
|
|
||||||
|
// Access datasets
|
||||||
|
auto counts_data = nexus.GetDataset<int>("/raw_data_1/detector_1/counts");
|
||||||
|
const auto& counts = counts_data.GetData();
|
||||||
|
const auto& dims = counts_data.GetDimensions();
|
||||||
|
|
||||||
|
// Dump file contents
|
||||||
|
nexus.Dump();
|
||||||
|
|
||||||
|
// Write to new file
|
||||||
|
nexus.WriteNexusFile("output.nxs", 2); // IDF version 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creating Files from Scratch
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
nxH4::PNeXus nxs_out;
|
||||||
|
|
||||||
|
// Add datasets
|
||||||
|
std::vector<int> counts(16*66000, 0);
|
||||||
|
nxs_out.AddDataset<int>("/raw_data_1/detector_1/counts",
|
||||||
|
counts, {1, 16, 66000},
|
||||||
|
nxH4::H4DataType::INT32);
|
||||||
|
|
||||||
|
// Add attributes
|
||||||
|
nxs_out.AddDatasetAttribute<int>("/raw_data_1/detector_1/counts",
|
||||||
|
"units", std::string("counts"));
|
||||||
|
|
||||||
|
// Add group attributes
|
||||||
|
nxs_out.AddGroupAttribute("/raw_data_1", "NX_class", std::string("NXentry"));
|
||||||
|
|
||||||
|
// Write file
|
||||||
|
nxs_out.WriteNexusFile("output.nxs");
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Compatibility with h5nexus
|
||||||
|
|
||||||
|
The h4nexus API is designed to be compatible with h5nexus. The main differences are:
|
||||||
|
|
||||||
|
- Namespace: `nxH4::` instead of `nxH5::`
|
||||||
|
- Data types: `H4DataType` enum instead of `H5::DataType`
|
||||||
|
- Dimensions: Uses `uint32_t` instead of `hsize_t`
|
||||||
|
|
||||||
|
Code migration typically requires only:
|
||||||
|
1. Changing namespace from `nxH5` to `nxH4`
|
||||||
|
2. Changing `H5::PredType::NATIVE_INT` to `nxH4::H4DataType::INT32` (etc.)
|
||||||
|
3. Changing dimension types from `hsize_t` to `uint32_t`
|
||||||
|
|
||||||
|
## Supported Data Types
|
||||||
|
|
||||||
|
- `H4DataType::INT32` - 32-bit signed integer
|
||||||
|
- `H4DataType::FLOAT32` - 32-bit floating point
|
||||||
|
- `H4DataType::FLOAT64` - 64-bit floating point
|
||||||
|
- `H4DataType::CHAR8` - 8-bit character/string
|
||||||
|
- `H4DataType::UINT32` - 32-bit unsigned integer
|
||||||
|
- `H4DataType::INT16` - 16-bit signed integer
|
||||||
|
- `H4DataType::UINT16` - 16-bit unsigned integer
|
||||||
|
- `H4DataType::INT8` - 8-bit signed integer
|
||||||
|
- `H4DataType::UINT8` - 8-bit unsigned integer
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Generate Doxygen documentation (if Doxygen is installed):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make doc
|
||||||
|
```
|
||||||
|
|
||||||
|
Documentation will be generated in the `doc/html` directory.
|
||||||
|
|
||||||
|
## Differences from HDF5
|
||||||
|
|
||||||
|
HDF4 has some limitations compared to HDF5:
|
||||||
|
- No true hierarchical groups (simulated using naming conventions)
|
||||||
|
- Less flexible attribute handling
|
||||||
|
- Different maximum name lengths
|
||||||
|
- C API instead of C++ API
|
||||||
|
|
||||||
|
The h4nexus library abstracts these differences to provide a similar interface to h5nexus.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
GNU General Public License v2 (GPLv2)
|
||||||
|
|
||||||
|
## Contacts
|
||||||
|
|
||||||
|
Andreas Suter <andreas.suter@psi.ch>
|
||||||
35
src/external/nexus/examples/hdf4/git_revision.sh
vendored
Executable file
35
src/external/nexus/examples/hdf4/git_revision.sh
vendored
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script to create git-revision.h with current git information
|
||||||
|
# Usage: git_revision.sh [output_directory]
|
||||||
|
|
||||||
|
output_dir="${1:-.}"
|
||||||
|
output_file="${output_dir}/git-revision.h"
|
||||||
|
|
||||||
|
# Check if we're in a git repository
|
||||||
|
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||||
|
echo "Not in a git repository, skipping git-revision.h generation"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get git information
|
||||||
|
git_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
||||||
|
git_hash=$(git rev-parse --short HEAD 2>/dev/null)
|
||||||
|
git_date=$(git log -1 --format=%cd --date=short 2>/dev/null)
|
||||||
|
|
||||||
|
# Create header file
|
||||||
|
cat > "$output_file" << EOF
|
||||||
|
// This file is auto-generated by git_revision.sh
|
||||||
|
// Do not edit manually
|
||||||
|
|
||||||
|
#ifndef GIT_REVISION_H
|
||||||
|
#define GIT_REVISION_H
|
||||||
|
|
||||||
|
#define GIT_BRANCH "$git_branch"
|
||||||
|
#define GIT_HASH "$git_hash"
|
||||||
|
#define GIT_DATE "$git_date"
|
||||||
|
|
||||||
|
#endif // GIT_REVISION_H
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "Generated $output_file"
|
||||||
447
src/external/nexus/examples/hdf4/main.cpp
vendored
Normal file
447
src/external/nexus/examples/hdf4/main.cpp
vendored
Normal file
@@ -0,0 +1,447 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
|
||||||
|
main.cpp
|
||||||
|
|
||||||
|
Author: Andreas Suter
|
||||||
|
e-mail: andreas.suter@psi.ch
|
||||||
|
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||||
|
* andreas.suter@psi.ch *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file main.cpp
|
||||||
|
* @brief Command-line interface for the h4nexus NeXus HDF4 file reader/writer
|
||||||
|
*
|
||||||
|
* This file contains the main() function and command-line interface for the
|
||||||
|
* h4nexus program. It provides functionality to:
|
||||||
|
* - Read and display NeXus HDF4 files
|
||||||
|
* - Write NeXus HDF4 files using the PNXdata approach
|
||||||
|
* - Calculate dead time corrections for muon detector data
|
||||||
|
*
|
||||||
|
* **Command-Line Options:**
|
||||||
|
* - --fn <file>: Input NeXus HDF4 file (required)
|
||||||
|
* - --out <file>: Output NeXus HDF4 file (optional)
|
||||||
|
* - --debug, -d: Enable debug output
|
||||||
|
* - --dead_time_estimate, -dt: Calculate dead time corrections
|
||||||
|
* - --help, -h: Display help message
|
||||||
|
* - --version, -v: Display version information
|
||||||
|
*
|
||||||
|
* @author Andreas Suter
|
||||||
|
* @date 2007-2026
|
||||||
|
* @copyright GNU General Public License v2
|
||||||
|
* @version 1.0
|
||||||
|
*
|
||||||
|
* @see nxH4::PNeXus
|
||||||
|
* @see nxH4::PNeXusDeadTime
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
#include <mfhdf.h>
|
||||||
|
|
||||||
|
#include "PNeXus.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_GIT_REV_H
|
||||||
|
#include "git-revision.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* @brief Display command-line syntax and help information
|
||||||
|
*
|
||||||
|
* Prints the usage syntax and available command-line options for the h4nexus
|
||||||
|
* program to stdout and exits the program.
|
||||||
|
*/
|
||||||
|
void h4nexus_syntax() {
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "usage: h4nexus [--help | -h] |" << std::endl;
|
||||||
|
std::cout << " [--version | -v] |" << std::endl;
|
||||||
|
std::cout << " --fn <fln> [--debug | -d]" << std::endl;
|
||||||
|
std::cout << " [--dead_time_estimate | -dt]]" << std::endl;
|
||||||
|
std::cout << " [--out <fout>]" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "options:" << std::endl;
|
||||||
|
std::cout << " --help, -h: this help." << std::endl;
|
||||||
|
std::cout << " --version, -v: version of h4nexus." << std::endl;
|
||||||
|
std::cout << " --fn <fln>: nexus hdf4 input file name <fn>." << std::endl;
|
||||||
|
std::cout << " --dead_time_estimate, -dt: dead time estimate for the read hdf4 nexus file." << std::endl;
|
||||||
|
std::cout << " --debug, -d: print additional debug information." << std::endl;
|
||||||
|
std::cout << " --out <fout>: write the required datasets of a nexus hdf4 file to file " << std::endl;
|
||||||
|
std::cout << " with name <fout>. Only makes sense together with the option --fn <fln>." << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* @brief Calculate dead time corrections for muon detector data
|
||||||
|
*
|
||||||
|
* Estimates dead time corrections for each detector in the NeXus file using
|
||||||
|
* the PNeXusDeadTime class and ROOT Minuit2 minimization.
|
||||||
|
*
|
||||||
|
* @param nxs Pointer to the PNeXus object containing the data
|
||||||
|
* @param debug If true, print additional debug information
|
||||||
|
*
|
||||||
|
* @see nxH4::PNeXusDeadTime
|
||||||
|
*/
|
||||||
|
void h4nexus_deadTimeEstimate(const nxH4::PNeXus *nxs, bool debug)
|
||||||
|
{
|
||||||
|
if (debug) {
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << std::endl << "+++++++++++++++++++";
|
||||||
|
std::cout << std::endl << "in deadTimeEstimate";
|
||||||
|
std::cout << std::endl << "+++++++++++++++++++";
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxH4::PNeXusDeadTime ndt(nxs, debug);
|
||||||
|
auto dims = ndt.GetDimensions();
|
||||||
|
for (unsigned int i=0; i<dims[1]; i++) {
|
||||||
|
ndt.minimize(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* @brief Write NeXus HDF4 file using the PNXdata approach
|
||||||
|
*
|
||||||
|
* Writes all datasets from the PNeXus data map to a new NeXus HDF4 file.
|
||||||
|
* This function uses the WriteNexusFile() method to create a complete
|
||||||
|
* NeXus file with all groups, datasets, and attributes.
|
||||||
|
*
|
||||||
|
* @param nxs Pointer to the PNeXus object containing the data to write
|
||||||
|
* @param outFileName Output filename for the NeXus HDF4 file
|
||||||
|
* @param debug If true, print additional debug information
|
||||||
|
*
|
||||||
|
* @note Currently only supports IDF version 2 files
|
||||||
|
*
|
||||||
|
* @see nxH4::PNeXus::WriteNexusFile()
|
||||||
|
*/
|
||||||
|
void h4nexus_writeTest(const nxH4::PNeXus *nxs, const std::string& outFileName, bool debug)
|
||||||
|
{
|
||||||
|
if (debug) {
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "++++++++++++++++++++" << std::endl;
|
||||||
|
std::cout << "Writing NeXus file" << std::endl;
|
||||||
|
std::cout << "++++++++++++++++++++" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxs->GetIdfVersion() == 1) {
|
||||||
|
std::cerr << "Error: IDF v1 write not yet implemented" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write using the read object's data
|
||||||
|
int result = const_cast<nxH4::PNeXus*>(nxs)->WriteNexusFile(outFileName, nxs->GetIdfVersion());
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
std::cout << "Successfully wrote: " << outFileName << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Failed to write file: " << outFileName << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write data from scratch
|
||||||
|
|
||||||
|
std::unique_ptr<nxH4::PNeXus> nxs_out = std::make_unique<nxH4::PNeXus>();
|
||||||
|
|
||||||
|
std::vector<int> ival;
|
||||||
|
std::vector<float> fval;
|
||||||
|
std::vector<std::string> sval;
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
// raw_data_1
|
||||||
|
// ----------
|
||||||
|
|
||||||
|
// IDF version
|
||||||
|
ival.push_back(2);
|
||||||
|
nxs_out->AddDataset<int>("/raw_data_1/IDF_version", ival, {1}, nxH4::H4DataType::INT32);
|
||||||
|
ival.clear();
|
||||||
|
|
||||||
|
// add group attribute to '/raw_data_1'
|
||||||
|
nxs_out->AddGroupAttribute("/raw_data_1", "NX_class", std::string("NXentry"));
|
||||||
|
|
||||||
|
// beamline
|
||||||
|
sval.push_back("piE3");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/beamline", sval, {1}, nxH4::H4DataType::CHAR8);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// definition
|
||||||
|
sval.push_back("muonTD");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/definition", sval, {1}, nxH4::H4DataType::CHAR8);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// run_number
|
||||||
|
ival.push_back(1234);
|
||||||
|
nxs_out->AddDataset<int>("/raw_data_1/run_number", ival, {1}, nxH4::H4DataType::INT32);
|
||||||
|
ival.clear();
|
||||||
|
|
||||||
|
// title
|
||||||
|
sval.push_back("this is the run title.");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/title", sval, {1}, nxH4::H4DataType::CHAR8);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// start time
|
||||||
|
sval.push_back("2026-01-01T01:02:03");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/start_time", sval, {1}, nxH4::H4DataType::CHAR8);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// end time
|
||||||
|
sval.push_back("2026-01-01T02:03:42");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/end_time", sval, {1}, nxH4::H4DataType::CHAR8);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// experiment_identifier - pgroup for PSI
|
||||||
|
sval.push_back("p18324");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/experiment_identifier", sval, {1}, nxH4::H4DataType::CHAR8);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// -------------------
|
||||||
|
// detector_1 (NXdata)
|
||||||
|
// -------------------
|
||||||
|
|
||||||
|
// add group attribute to /raw_data_1/instrument
|
||||||
|
nxs_out->AddGroupAttribute("/raw_data_1/detector_1", "NX_class", std::string("NXdata"));
|
||||||
|
|
||||||
|
// counts
|
||||||
|
std::vector<int> counts(16*66000, 42); // data 16 histos with length 66000
|
||||||
|
nxs_out->AddDataset<int>("/raw_data_1/detector_1/counts", counts, {1, 16, 66000}, nxH4::H4DataType::INT32);
|
||||||
|
|
||||||
|
// attributes for counts
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "signal", 1);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "axes", std::string("period_index,spectrum_index,raw_time"));
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "long_name", std::string("positron_counts"));
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "t0_bin", 2741);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "first_good_bin", 2741);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "last_good_bin", 66000);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "units", std::string("counts"));
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "target", std::string("/raw_data_1/instrument/detector_1/counts"));
|
||||||
|
|
||||||
|
// raw_time
|
||||||
|
std::vector<float> raw_time(66000, 0.0);
|
||||||
|
for (unsigned int i=0; i<raw_time.size(); i++)
|
||||||
|
raw_time[i] = 0.1953125f*1.0e-3*((float)i-2741.0f+0.5f);
|
||||||
|
nxs_out->AddDataset<float>("/raw_data_1/detector_1/raw_time", raw_time, {66000}, nxH4::H4DataType::FLOAT32);
|
||||||
|
|
||||||
|
// attributes raw_time
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/detector_1/raw_time", "units", std::string("microseconds"));
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/detector_1/raw_time", "target", std::string("/raw_data_1/instrument/detector_1/raw_time"));
|
||||||
|
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
// instrument
|
||||||
|
// ----------
|
||||||
|
|
||||||
|
// add group attribute to /raw_data_1/instrument
|
||||||
|
nxs_out->AddGroupAttribute("/raw_data_1/instrument", "NX_class", std::string("NXinstrument"));
|
||||||
|
|
||||||
|
// name
|
||||||
|
sval.push_back("LEM");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/instrument/name", sval, {1}, nxH4::H4DataType::CHAR8);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// ------
|
||||||
|
// source
|
||||||
|
// ------
|
||||||
|
|
||||||
|
// add group attribute to /raw_data_1/instrument/source
|
||||||
|
nxs_out->AddGroupAttribute("/raw_data_1/instrument/source", "NX_class", std::string("NXsource"));
|
||||||
|
|
||||||
|
// name
|
||||||
|
sval.push_back("PSI");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/instrument/source/name", sval, {1}, nxH4::H4DataType::CHAR8);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// type
|
||||||
|
sval.push_back("continuous muon source");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/instrument/source/types", sval, {1}, nxH4::H4DataType::CHAR8);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// probe
|
||||||
|
sval.push_back("postive muons");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/instrument/source/probe", sval, {1}, nxH4::H4DataType::CHAR8);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// -----------------------
|
||||||
|
// detector_1 (NXdetector)
|
||||||
|
// -----------------------
|
||||||
|
|
||||||
|
// add group attribute to /raw_data_1/instrument/detector_1
|
||||||
|
nxs_out->AddGroupAttribute("/raw_data_1/instrument/detector_1", "NX_class", std::string("NXdetector"));
|
||||||
|
|
||||||
|
// counts
|
||||||
|
nxs_out->AddDataset<int>("/raw_data_1/instrument/detector_1/counts", counts, {1, 16, 66000}, nxH4::H4DataType::INT32);
|
||||||
|
|
||||||
|
// attributes for counts
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "signal", 1);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "axes", std::string("period_index,spectrum_index,raw_time"));
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "long_name", std::string("positron_counts"));
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "t0_bin", 2741);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "first_good_bin", 2741);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "last_good_bin", 66000);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "units", std::string("counts"));
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "target", std::string("/raw_data_1/instrument/detector_1/counts"));
|
||||||
|
|
||||||
|
// raw_time
|
||||||
|
nxs_out->AddDataset<float>("/raw_data_1/instrument/detector_1/raw_time", raw_time, {66000}, nxH4::H4DataType::FLOAT32);
|
||||||
|
|
||||||
|
// attributes raw_time
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/instrument/detector_1/raw_time", "units", std::string("microseconds"));
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/instrument/detector_1/raw_time", "target", std::string("/raw_data_1/instrument/detector_1/raw_time"));
|
||||||
|
|
||||||
|
// resolution
|
||||||
|
fval.push_back(195.3125);
|
||||||
|
nxs_out->AddDataset<float>("/raw_data_1/instrument/detector_1/resolution", fval, {1}, nxH4::H4DataType::FLOAT32);
|
||||||
|
fval.clear();
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/instrument/detector_1/resolution",
|
||||||
|
"units", std::string("picoseconds"));
|
||||||
|
|
||||||
|
// spectrum_index
|
||||||
|
for (unsigned int i=0; i<66000; i++)
|
||||||
|
ival.push_back(i+1);
|
||||||
|
nxs_out->AddDataset<int>("/raw_data_1/instrument/detector_1/spectrum_index", ival, {66000}, nxH4::H4DataType::INT32);
|
||||||
|
ival.clear();
|
||||||
|
|
||||||
|
// dead_time
|
||||||
|
std::vector<float> deadTime(66000, 0.0);
|
||||||
|
nxs_out->AddDataset<float>("/raw_data_1/instrument/detector_1/dead_time", deadTime, {66000}, nxH4::H4DataType::FLOAT32);
|
||||||
|
|
||||||
|
// attributes dead_time
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/instrument/detector_1/dead_time", "available", 0);
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/instrument/detector_1/dead_time", "units", std::string("microseconds"));
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/instrument/detector_1/dead_time", "target", std::string("/raw_data_1/instrument/detector_1/dead_time"));
|
||||||
|
|
||||||
|
// add root attributes
|
||||||
|
// file name
|
||||||
|
nxs_out->AddRootAttribute("file_name", std::string("_test.nxs"));
|
||||||
|
// date-time
|
||||||
|
std::time_t time = std::time({});
|
||||||
|
char timeString[std::size("yyyy-mm-ddThh:mm:ssZ")];
|
||||||
|
std::strftime(std::data(timeString), std::size(timeString),
|
||||||
|
"%FT%TZ", std::gmtime(&time));
|
||||||
|
nxs_out->AddRootAttribute("file_time", std::string(timeString));
|
||||||
|
// NeXus version
|
||||||
|
nxs_out->AddRootAttribute("NeXus_Version", std::string("4.3.0"));
|
||||||
|
// hdf4 version
|
||||||
|
nxs_out->AddRootAttribute("HDF4_Version", std::string(nxs->GetHdf4Version()));
|
||||||
|
// creator
|
||||||
|
nxs_out->AddRootAttribute("creator", std::string("h4nexus - PSI"));
|
||||||
|
|
||||||
|
nxs_out->WriteNexusFile("_test.nxs");
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* @brief Main entry point for the h4nexus program
|
||||||
|
*
|
||||||
|
* Parses command-line arguments and performs the requested operations:
|
||||||
|
* - Read and display NeXus HDF4 file information
|
||||||
|
* - Write NeXus HDF4 files with modified data
|
||||||
|
* - Calculate dead time corrections
|
||||||
|
*
|
||||||
|
* @param argc Number of command-line arguments
|
||||||
|
* @param argv Array of command-line argument strings
|
||||||
|
*
|
||||||
|
* @return 0 on success, non-zero on error
|
||||||
|
*
|
||||||
|
* @see h4nexus_syntax() for available command-line options
|
||||||
|
*/
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
std::string fileName{""};
|
||||||
|
std::string fileNameOut{""};
|
||||||
|
bool printDebug{false};
|
||||||
|
bool deadTimeEstimate{false};
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
h4nexus_syntax();
|
||||||
|
|
||||||
|
for (int i=1; i<argc; i++) {
|
||||||
|
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
|
||||||
|
h4nexus_syntax();
|
||||||
|
} else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#ifdef HAVE_GIT_REV_H
|
||||||
|
std::cout << std::endl << "h4nexus version: " << H4NEXUS_VERSION << ", git-branch: " << GIT_BRANCH << ", git-hash: " << GIT_HASH << std::endl << std::endl;
|
||||||
|
#else
|
||||||
|
std::cout << std::endl << "h4nexus version: " << H4NEXUS_VERSION << std::endl << std::endl;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_GIT_REV_H
|
||||||
|
std::cout << std::endl << "h4nexus git-branch: " << GIT_BRANCH << ", git-hash: " << GIT_HASH << std::endl << std::endl;
|
||||||
|
#else
|
||||||
|
std::cout << std::endl << "h4nexus version: unknown." << std::endl << std::endl;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
} else if (!strcmp(argv[i], "--fn")) {
|
||||||
|
if (i+1 >= argc) {
|
||||||
|
std::cout << std::endl << "**ERROR** found --fn without <fln>." << std::endl;
|
||||||
|
h4nexus_syntax();
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
fileName = argv[i];
|
||||||
|
} else if (!strcmp(argv[i], "-dt") || !strcmp(argv[i], "--dead_time_estimate")) {
|
||||||
|
deadTimeEstimate = true;
|
||||||
|
} else if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) {
|
||||||
|
printDebug = true;
|
||||||
|
} else if (!strcmp(argv[i], "--out")) {
|
||||||
|
if (i+1 >= argc) {
|
||||||
|
std::cout << std::endl << "**ERROR** found --out without <fout>." << std::endl;
|
||||||
|
h4nexus_syntax();
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
fileNameOut = argv[i];
|
||||||
|
} else {
|
||||||
|
h4nexus_syntax();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileName.empty()) {
|
||||||
|
std::cerr << std::endl;
|
||||||
|
std::cerr << "**ERROR** <fln> is missing." << std::endl;
|
||||||
|
std::cerr << std::endl;
|
||||||
|
h4nexus_syntax();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<nxH4::PNeXus> nxs = std::make_unique<nxH4::PNeXus>(fileName, printDebug);
|
||||||
|
|
||||||
|
nxs->Dump();
|
||||||
|
|
||||||
|
if (deadTimeEstimate) {
|
||||||
|
h4nexus_deadTimeEstimate(nxs.get(), printDebug);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileNameOut.empty()) {
|
||||||
|
h4nexus_writeTest(nxs.get(), fileNameOut, printDebug);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
119
src/external/nexus/examples/hdf5/CMakeLists.txt
vendored
Normal file
119
src/external/nexus/examples/hdf5/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# - h5nexus
|
||||||
|
cmake_minimum_required(VERSION 3.26)
|
||||||
|
|
||||||
|
project(h5nexus VERSION 0.1.0 LANGUAGES CXX)
|
||||||
|
|
||||||
|
#--- set C++ standard ---------------------------------------------------------
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
#--- set a default build type if none was specified ---------------------------
|
||||||
|
set(default_build_type "Release")
|
||||||
|
|
||||||
|
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
|
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
|
||||||
|
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE
|
||||||
|
STRING "Choose the type of build." FORCE)
|
||||||
|
# Set the possible values of build type for cmake-gui
|
||||||
|
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||||
|
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
#--- check for pkg-config -----------------------------------------------------
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
|
#--- check for git ------------------------------------------------------------
|
||||||
|
find_package(Git REQUIRED)
|
||||||
|
|
||||||
|
#--- check for HDF5 -----------------------------------------------------------
|
||||||
|
find_package(HDF5 REQUIRED COMPONENTS CXX)
|
||||||
|
if(NOT HDF5_FOUND)
|
||||||
|
message(FATAL_ERROR "HDF5 C++ library not found")
|
||||||
|
endif()
|
||||||
|
include_directories(${HDF5_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
#--- check for ROOT -----------------------------------------------------------
|
||||||
|
find_package(ROOT 6.36 REQUIRED COMPONENTS Minuit2)
|
||||||
|
if (ROOT_miniut2_FOUND)
|
||||||
|
execute_process(COMMAND root-config --bindir OUTPUT_VARIABLE ROOT_BINDIR)
|
||||||
|
string(STRIP ${ROOT_BINDIR} ROOT_BINDIR)
|
||||||
|
execute_process(COMMAND root-config --version OUTPUT_VARIABLE ROOT_VERSION)
|
||||||
|
string(STRIP ${ROOT_VERSION} ROOT_VERSION)
|
||||||
|
message("-- Found ROOT: ${ROOT_BINDIR} (found version: ${ROOT_VERSION})")
|
||||||
|
#---Define useful ROOT functions and macros (e.g. ROOT_GENERATE_DICTIONARY)
|
||||||
|
include(${ROOT_USE_FILE})
|
||||||
|
endif (ROOT_miniut2_FOUND)
|
||||||
|
|
||||||
|
#--- all checks done -> feed config.h -----------------------------------------
|
||||||
|
set(HAVE_CONFIG_H 1 CACHE INTERNAL "config.h is available")
|
||||||
|
configure_file(${CMAKE_SOURCE_DIR}/cmake/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
|
||||||
|
#--- check if project source is a git repo ------------------------------------
|
||||||
|
if (EXISTS "${CMAKE_SOURCE_DIR}/.git/HEAD")
|
||||||
|
message(STATUS "is a git repo")
|
||||||
|
set(IS_GIT_REPO 1)
|
||||||
|
else ()
|
||||||
|
message(STATUS "is NOT a git repo")
|
||||||
|
set(IS_GIT_REPO 0)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
#--- start create git-revision.h ----------------------------------------------
|
||||||
|
if (IS_GIT_REPO)
|
||||||
|
execute_process(COMMAND sh ${CMAKE_SOURCE_DIR}/src/git_revision.sh)
|
||||||
|
|
||||||
|
set(HAVE_GIT_REV_H "-DHAVE_GIT_REV_H")
|
||||||
|
set(GIT_REV_H "git-revision.h")
|
||||||
|
else (IS_GIT_REPO)
|
||||||
|
set(HAVE_GIT_REV_H "")
|
||||||
|
set(GIT_REV_H "")
|
||||||
|
endif (IS_GIT_REPO)
|
||||||
|
|
||||||
|
#--- end create git-revision.h ------------------------------------------------
|
||||||
|
|
||||||
|
#--- write summary of the installation
|
||||||
|
cmake_host_system_information(RESULT PROCESSOR QUERY PROCESSOR_DESCRIPTION)
|
||||||
|
|
||||||
|
message("")
|
||||||
|
message("|-----------------------------------------------------------------------|")
|
||||||
|
message("| |")
|
||||||
|
message("| Summary |")
|
||||||
|
message("| |")
|
||||||
|
message("|-----------------------------------------------------------------------|")
|
||||||
|
message("")
|
||||||
|
message(" System: ${CMAKE_HOST_SYSTEM_NAME} ${CMAKE_SYSTEM_PROCESSOR} - ${CMAKE_HOST_SYSTEM_VERSION}")
|
||||||
|
message(" Processor: ${PROCESSOR} (${CMAKE_SYSTEM_PROCESSOR})")
|
||||||
|
message(" ----------")
|
||||||
|
message("")
|
||||||
|
message(" h5nexus Version: ${musrfit_VERSION}")
|
||||||
|
message(" ----------------")
|
||||||
|
message("")
|
||||||
|
message(" Build Type: ${CMAKE_BUILD_TYPE}")
|
||||||
|
message(" -----------")
|
||||||
|
message("")
|
||||||
|
message(" Requirements:")
|
||||||
|
message(" -------------")
|
||||||
|
message("")
|
||||||
|
message(" HDF5 found in ${HDF5_INCLUDE_DIRS}, Version: ${HDF5_VERSION}")
|
||||||
|
message(" ROOT found in ${ROOT_INCLUDE_DIRS}, Version: ${ROOT_VERSION}")
|
||||||
|
message("")
|
||||||
|
message(" Installation directories:")
|
||||||
|
message(" -------------------------")
|
||||||
|
message("")
|
||||||
|
message(" Programs : ${CMAKE_INSTALL_PREFIX}/bin")
|
||||||
|
message("")
|
||||||
|
message("-------------------------------------------------------------------------")
|
||||||
|
message("")
|
||||||
|
|
||||||
|
#--- add executable -----------------------------------------------------------
|
||||||
|
add_executable(h5nexus
|
||||||
|
../../PNeXus.cpp
|
||||||
|
main.cpp)
|
||||||
|
target_compile_options(h5nexus BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_REV_H}")
|
||||||
|
target_include_directories(h5nexus
|
||||||
|
BEFORE PRIVATE
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/build>
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/../..>
|
||||||
|
$<BUILD_INTERFACE:${ROOT_INCLUDE_DIRS}>
|
||||||
|
)
|
||||||
|
target_link_libraries(h5nexus ${HDF5_CXX_LIBRARIES} ${ROOT_LIBRARIES})
|
||||||
5
src/external/nexus/examples/hdf5/cmake/config.h.in
vendored
Normal file
5
src/external/nexus/examples/hdf5/cmake/config.h.in
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// config.h
|
||||||
|
|
||||||
|
#define PACKAGE_VERSION "@PROJECT_VERSION@"
|
||||||
|
#define BUILD_TYPE "@CMAKE_BUILD_TYPE@"
|
||||||
|
|
||||||
8
src/external/nexus/examples/hdf5/cmake/git-revision.h.in
vendored
Normal file
8
src/external/nexus/examples/hdf5/cmake/git-revision.h.in
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef GIT_VERSION_H
|
||||||
|
#define GIT_VERSION_H
|
||||||
|
|
||||||
|
#define GIT_BRANCH "@GIT_BRANCH@"
|
||||||
|
#define GIT_CURRENT_SHA1 @GIT_CURRENT_SHA1@
|
||||||
|
|
||||||
|
#endif // GIT_VERSION_H
|
||||||
|
|
||||||
198
src/external/nexus/examples/hdf5/docu/README.md
vendored
Normal file
198
src/external/nexus/examples/hdf5/docu/README.md
vendored
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
# h5nexus Documentation
|
||||||
|
|
||||||
|
This directory contains documentation for the h5nexus project.
|
||||||
|
|
||||||
|
## Available Documentation
|
||||||
|
|
||||||
|
- **Usage.md** - Comprehensive usage guide with detailed examples and workflow patterns
|
||||||
|
- **mainpage.md** - Main page for Doxygen-generated API documentation
|
||||||
|
|
||||||
|
## Generating API Documentation
|
||||||
|
|
||||||
|
The project uses [Doxygen](https://www.doxygen.nl/) to generate comprehensive API documentation from source code comments.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- **Doxygen** (required) - Install with:
|
||||||
|
```bash
|
||||||
|
# macOS
|
||||||
|
brew install doxygen
|
||||||
|
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt-get install doxygen
|
||||||
|
|
||||||
|
# Fedora/RHEL
|
||||||
|
sudo dnf install doxygen
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Graphviz** (optional, recommended) - For generating diagrams:
|
||||||
|
```bash
|
||||||
|
# macOS
|
||||||
|
brew install graphviz
|
||||||
|
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt-get install graphviz
|
||||||
|
|
||||||
|
# Fedora/RHEL
|
||||||
|
sudo dnf install graphviz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Method 1: Using CMake (Recommended)
|
||||||
|
|
||||||
|
If you've already configured your build with CMake:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd build
|
||||||
|
make doc
|
||||||
|
```
|
||||||
|
|
||||||
|
This will generate HTML documentation in the `doc/html/` directory.
|
||||||
|
|
||||||
|
### Method 2: Using Doxygen Directly
|
||||||
|
|
||||||
|
From the project root directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
doxygen Doxyfile
|
||||||
|
```
|
||||||
|
|
||||||
|
This will also generate HTML documentation in the `doc/html/` directory.
|
||||||
|
|
||||||
|
## Viewing the Documentation
|
||||||
|
|
||||||
|
After generation, open the main documentation page in your web browser:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# macOS
|
||||||
|
open doc/html/index.html
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
xdg-open doc/html/index.html
|
||||||
|
|
||||||
|
# Or manually navigate to: file:///path/to/h5nexus/doc/html/index.html
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation Structure
|
||||||
|
|
||||||
|
The generated documentation includes:
|
||||||
|
|
||||||
|
- **Main Page** - Overview, quick start guide, and architecture description
|
||||||
|
- **Classes** - Detailed documentation for all classes:
|
||||||
|
- `nxH5::PNeXus` - Main NeXus file reader/writer class
|
||||||
|
- `nxH5::PNXdata<T>` - Template class for dataset storage
|
||||||
|
- `nxH5::PNeXusDeadTime` - Dead time correction calculator
|
||||||
|
- **Files** - Source file documentation
|
||||||
|
- **Namespaces** - Namespace documentation (nxH5)
|
||||||
|
- **Examples** - Code examples from the documentation
|
||||||
|
- **Class Hierarchy** - Visual class inheritance diagrams
|
||||||
|
- **Call Graphs** - Function call graphs (if Graphviz is available)
|
||||||
|
- **Include Dependency Graphs** - Header file dependency visualization
|
||||||
|
|
||||||
|
## Documentation Features
|
||||||
|
|
||||||
|
The Doxygen configuration includes:
|
||||||
|
|
||||||
|
- **Full source browsing** - Browse annotated source code
|
||||||
|
- **Search functionality** - Fast search across all documentation
|
||||||
|
- **Interactive SVG diagrams** - Zoomable class and call graphs
|
||||||
|
- **Cross-references** - Links between related classes and functions
|
||||||
|
- **Syntax highlighting** - Colored code examples
|
||||||
|
- **Responsive layout** - Works on desktop and mobile browsers
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The Doxygen configuration is stored in `Doxyfile` at the project root. Key settings:
|
||||||
|
|
||||||
|
- **Input files**: `inc/`, `src/`, `docu/mainpage.md`
|
||||||
|
- **Output directory**: `doc/`
|
||||||
|
- **Output format**: HTML (LaTeX disabled)
|
||||||
|
- **Graphs**: Enabled if Graphviz/dot is available
|
||||||
|
- **Extract all**: Yes (documents all code, not just documented items)
|
||||||
|
- **Source browser**: Enabled
|
||||||
|
|
||||||
|
## Updating Documentation
|
||||||
|
|
||||||
|
To update the documentation after code changes:
|
||||||
|
|
||||||
|
1. Edit Doxygen comments in header/source files
|
||||||
|
2. Regenerate documentation: `make doc` or `doxygen Doxyfile`
|
||||||
|
3. Refresh your browser to see changes
|
||||||
|
|
||||||
|
### Doxygen Comment Style
|
||||||
|
|
||||||
|
The project uses Javadoc-style comments:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
/**
|
||||||
|
* @brief Brief description of the function
|
||||||
|
*
|
||||||
|
* Detailed description with more information about what
|
||||||
|
* the function does, how it works, and any important notes.
|
||||||
|
*
|
||||||
|
* @param arg1 Description of first parameter
|
||||||
|
* @param arg2 Description of second parameter
|
||||||
|
* @return Description of return value
|
||||||
|
* @throws ExceptionType Description of when this exception is thrown
|
||||||
|
*
|
||||||
|
* @note Important note about usage
|
||||||
|
* @warning Warning about potential issues
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* @code
|
||||||
|
* // Example usage
|
||||||
|
* MyClass obj;
|
||||||
|
* obj.myFunction(42, "test");
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
void myFunction(int arg1, const std::string& arg2);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cleaning Generated Documentation
|
||||||
|
|
||||||
|
To remove generated documentation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rm -rf doc/html/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Doxygen not found" during CMake configuration
|
||||||
|
|
||||||
|
Install Doxygen (see Prerequisites above), then reconfigure:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
```
|
||||||
|
|
||||||
|
### Graphs/diagrams not generating
|
||||||
|
|
||||||
|
Install Graphviz (see Prerequisites above), then regenerate:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make doc
|
||||||
|
# or
|
||||||
|
doxygen Doxyfile
|
||||||
|
```
|
||||||
|
|
||||||
|
### Broken links in documentation
|
||||||
|
|
||||||
|
Ensure all referenced files exist and paths in Doxyfile are correct. The documentation system expects:
|
||||||
|
- Source files in `inc/` and `src/`
|
||||||
|
- Main page at `docu/mainpage.md`
|
||||||
|
|
||||||
|
### Documentation looks outdated
|
||||||
|
|
||||||
|
Clear the output directory and regenerate:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rm -rf doc/html/
|
||||||
|
make doc
|
||||||
|
```
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
- [Doxygen Manual](https://www.doxygen.nl/manual/)
|
||||||
|
- [Doxygen Special Commands](https://www.doxygen.nl/manual/commands.html)
|
||||||
|
- [Markdown Support in Doxygen](https://www.doxygen.nl/manual/markdown.html)
|
||||||
2036
src/external/nexus/examples/hdf5/docu/Usage.md
vendored
Normal file
2036
src/external/nexus/examples/hdf5/docu/Usage.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
27
src/external/nexus/examples/hdf5/git_revision.sh
vendored
Executable file
27
src/external/nexus/examples/hdf5/git_revision.sh
vendored
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "-- Generating header for git hash"
|
||||||
|
GIT_HEADER="git-revision.h"
|
||||||
|
[ -d src ] || mkdir src
|
||||||
|
|
||||||
|
GIT_BRANCH=`git rev-parse --abbrev-ref HEAD`
|
||||||
|
|
||||||
|
GIT_VERSION=`git log -n 1 --pretty=format:"%ad - %h"`
|
||||||
|
if [ "$(grep -ics "$GIT_VERSION" $GIT_HEADER)" = 1 ]
|
||||||
|
then
|
||||||
|
echo "-- No need to generate new $GIT_HEADER - git hash is unchanged"
|
||||||
|
exit 0;
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "-- git branch is : " $GIT_BRANCH
|
||||||
|
echo "-- git version is : " $GIT_VERSION
|
||||||
|
|
||||||
|
echo "#ifndef GIT_VERSION_H" > $GIT_HEADER
|
||||||
|
echo "#define GIT_VERSION_H" >> $GIT_HEADER
|
||||||
|
echo "" >> $GIT_HEADER
|
||||||
|
echo "#define GIT_BRANCH \"$GIT_BRANCH\"" >> $GIT_HEADER
|
||||||
|
echo "#define GIT_CURRENT_SHA1 \"$GIT_VERSION\"" >> $GIT_HEADER
|
||||||
|
echo "" >> $GIT_HEADER
|
||||||
|
echo "#endif //GIT_VERSION_H" >> $GIT_HEADER
|
||||||
|
|
||||||
|
echo "-- file is generated into" $GIT_HEADER
|
||||||
572
src/external/nexus/examples/hdf5/main.cpp
vendored
Normal file
572
src/external/nexus/examples/hdf5/main.cpp
vendored
Normal file
@@ -0,0 +1,572 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
|
||||||
|
main.cpp
|
||||||
|
|
||||||
|
Author: Andreas Suter
|
||||||
|
e-mail: andreas.suter@psi.ch
|
||||||
|
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2007-2026 by Andreas Suter *
|
||||||
|
* andreas.suter@psi.ch *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file main.cpp
|
||||||
|
* @brief Command-line interface for the h5nexus NeXus HDF5 file reader/writer
|
||||||
|
*
|
||||||
|
* This file contains the main() function and command-line interface for the
|
||||||
|
* h5nexus program. It provides functionality to:
|
||||||
|
* - Read and display NeXus HDF5 files
|
||||||
|
* - Write NeXus HDF5 files using the PNXdata approach
|
||||||
|
* - Calculate dead time corrections for muon detector data
|
||||||
|
*
|
||||||
|
* **Command-Line Options:**
|
||||||
|
* - --fn <file>: Input NeXus HDF5 file (required)
|
||||||
|
* - --out <file>: Output NeXus HDF5 file (optional)
|
||||||
|
* - --debug, -d: Enable debug output
|
||||||
|
* - --dead_time_estimate, -dt: Calculate dead time corrections
|
||||||
|
* - --help, -h: Display help message
|
||||||
|
* - --version, -v: Display version information
|
||||||
|
*
|
||||||
|
* @author Andreas Suter
|
||||||
|
* @date 2007-2026
|
||||||
|
* @copyright GNU General Public License v2
|
||||||
|
* @version 1.0
|
||||||
|
*
|
||||||
|
* @see nxH5::PNeXus
|
||||||
|
* @see nxH5::PNeXusDeadTime
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <ctime>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "hdf5.h"
|
||||||
|
|
||||||
|
#include "PNeXus.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_GIT_REV_H
|
||||||
|
#include "git-revision.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* @brief Display command-line syntax and help information
|
||||||
|
*
|
||||||
|
* Prints the usage syntax and available command-line options for the h5nexus
|
||||||
|
* program to stdout and exits the program.
|
||||||
|
*/
|
||||||
|
void h5nexus_syntax() {
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "usage: h5nexus [--help | -h] |" << std::endl;
|
||||||
|
std::cout << " [--version | -v] |" << std::endl;
|
||||||
|
std::cout << " --fn <fln> [--debug | -d]" << std::endl;
|
||||||
|
std::cout << " [--dead_time_estimate | -dt]]" << std::endl;
|
||||||
|
std::cout << " [--out <fout>]" << std::endl;
|
||||||
|
std::cout << " [--data idx <dout>]" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "options:" << std::endl;
|
||||||
|
std::cout << " --help, -h: this help." << std::endl;
|
||||||
|
std::cout << " --version, -v: version of h5nexus." << std::endl;
|
||||||
|
std::cout << " --fn <fln>: nexus hdf5 input file name <fn>." << std::endl;
|
||||||
|
std::cout << " --dead_time_estimate, -dt: dead time estimate for the read hdf5 nexus file." << std::endl;
|
||||||
|
std::cout << " --debug, -d: print additional debug information." << std::endl;
|
||||||
|
std::cout << " --out <fout>: write the required datasets of a nexus hdf5 file to file " << std::endl;
|
||||||
|
std::cout << " with name <fout>. Only makes sense together with the option --fn <fln>." << std::endl;
|
||||||
|
std::cout << " --data idx <dout>: write a single ascii data set with idx to <dout>." << std::endl;
|
||||||
|
std::cout << " Only makes sense together with the option --fn <fln>." << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* @brief Calculate dead time corrections for muon detector data
|
||||||
|
*
|
||||||
|
* Estimates dead time corrections for each detector in the NeXus file using
|
||||||
|
* the PNeXusDeadTime class and ROOT Minuit2 minimization.
|
||||||
|
*
|
||||||
|
* @param nxs Pointer to the PNeXus object containing the data
|
||||||
|
* @param debug If true, print additional debug information
|
||||||
|
*
|
||||||
|
* @see nxH5::PNeXusDeadTime
|
||||||
|
*/
|
||||||
|
std::vector<float> h5nexus_deadTimeEstimate(const nxH5::PNeXus *nxs, bool debug)
|
||||||
|
{
|
||||||
|
if (debug) {
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << std::endl << "+++++++++++++++++++";
|
||||||
|
std::cout << std::endl << "in deadTimeEstimate";
|
||||||
|
std::cout << std::endl << "+++++++++++++++++++";
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxH5::PNeXusDeadTime ndt(nxs, debug);
|
||||||
|
auto dims = ndt.GetDimensions();
|
||||||
|
for (unsigned int i=0; i<dims[1]; i++) {
|
||||||
|
ndt.minimize(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ndt.GetDeadTimeEstimated();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void h5nexus_writeData(const nxH5::PNeXus *nxs, const std::string& fln, const std::string& dataOutFln, const int idx, const std::vector<float> dte)
|
||||||
|
{
|
||||||
|
std::cout << std::endl << "as35> in h5nexus_writeData: idf version: " << nxs->GetIdfVersion();
|
||||||
|
std::vector<int> counts;
|
||||||
|
std::vector<float> dt;
|
||||||
|
std::vector<long long unsigned int> dims;
|
||||||
|
float resolution{0.0};
|
||||||
|
int good_frames{0};
|
||||||
|
|
||||||
|
if (nxs->GetIdfVersion() == 1) {
|
||||||
|
if (nxs->HasDataset("/run/histogram_data_1/counts")) {
|
||||||
|
std::cout << std::endl << "as35> found counts in idf version 1";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto dataMap = nxs->GetDataMap();
|
||||||
|
if (nxs->HasDataset("/raw_data_1/detector_1/counts")) {
|
||||||
|
std::cout << std::endl << "as35> found counts in idf version 2";
|
||||||
|
auto counts_data = std::any_cast<nxH5::PNXdata<int>>(dataMap["/raw_data_1/detector_1/counts"]);
|
||||||
|
counts = counts_data.GetData();
|
||||||
|
auto dd = counts_data.GetDimensions();
|
||||||
|
for (auto i=0; i<dd.size(); i++)
|
||||||
|
dims.push_back(dd[i]);
|
||||||
|
|
||||||
|
std::cout << std::endl << "as35> dims: " << dims.size() << ": ";
|
||||||
|
for (auto i=0; i<dims.size(); i++)
|
||||||
|
std::cout << dims[i] << ", ";
|
||||||
|
}
|
||||||
|
if (idx >= dims[1]) {
|
||||||
|
std::cerr << std::endl << "**ERROR** idx=" << idx << " is >= number of dataset=" << dims[1] << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (nxs->HasDataset("/raw_data_1/detector_1/dead_time")) {
|
||||||
|
std::cout << std::endl << "as35> found dead_time in idf version 2";
|
||||||
|
auto dt_data = std::any_cast<nxH5::PNXdata<float>>(dataMap["/raw_data_1/detector_1/dead_time"]);
|
||||||
|
dt = dt_data.GetData();
|
||||||
|
}
|
||||||
|
if (nxs->HasDataset("/raw_data_1/instrument/detector_1/resolution")) {
|
||||||
|
std::cout << std::endl << "as35> found resolution in idf version 2";
|
||||||
|
auto r_data = std::any_cast<nxH5::PNXdata<int>>(dataMap["/raw_data_1/instrument/detector_1/resolution"]);
|
||||||
|
auto rr = r_data.GetData();
|
||||||
|
resolution = (float)rr[0];
|
||||||
|
if (r_data.HasAttribute("units")) {
|
||||||
|
std::string units = std::any_cast<std::string>(r_data.GetAttribute("units"));
|
||||||
|
if (units == "picoseconds")
|
||||||
|
resolution *= 1.0e-6;
|
||||||
|
else if (units == "nanoseconds")
|
||||||
|
resolution *= 1.0e-3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nxs->HasDataset("/raw_data_1/good_frames")) {
|
||||||
|
std::cout << std::endl << "as35> found good_frames in idf version 2";
|
||||||
|
auto gf_data = std::any_cast<nxH5::PNXdata<int>>(dataMap["/raw_data_1/good_frames"]);
|
||||||
|
good_frames = gf_data.GetData()[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
float dtei;
|
||||||
|
if (dte.size() > idx)
|
||||||
|
dtei = dte[idx];
|
||||||
|
|
||||||
|
// write dataset
|
||||||
|
std::ofstream fout(dataOutFln);
|
||||||
|
fout << "# NeXus fln: " << fln << std::endl;
|
||||||
|
fout << "# idx=" << idx << std::endl;
|
||||||
|
fout << "# resolution : " << resolution << " (us)" << std::endl;
|
||||||
|
fout << "# good_frames : " << good_frames << std::endl;
|
||||||
|
fout << "# dead_time : " << dt[idx] << " (us) : from file" << std::endl;
|
||||||
|
fout << "# dead_time : " << dtei << " (us) : from estimater" << std::endl;
|
||||||
|
fout << "# ------" << std::endl;
|
||||||
|
fout << "# raw counts, dead time corrected counts (file), dead time corrected counts (estimated)" << std::endl;
|
||||||
|
int cc{0}, dtcc{0}, dtecc{0};
|
||||||
|
// see https://docs.mantidproject.org/v3.9.0/algorithms/ApplyDeadTimeCorr-v1.html#algm-applydeadtimecorr
|
||||||
|
for (auto i=0; i<dims[2]; i++) {
|
||||||
|
cc = counts[i + idx*dims[2]];
|
||||||
|
dtcc = (int)((float)cc / (1.0 - (float)cc * (dt[idx]/(resolution*(float)good_frames))));
|
||||||
|
dtecc = (int)((float)cc / (1.0 - (float)cc * (dtei/(resolution*(float)good_frames))));
|
||||||
|
fout << cc << ", " << dtcc << ", " << dtecc << std::endl;
|
||||||
|
}
|
||||||
|
fout.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* @brief Write NeXus HDF5 file using the PNXdata approach
|
||||||
|
*
|
||||||
|
* Writes all datasets from the PNeXus data map to a new NeXus HDF5 file.
|
||||||
|
* This function uses the WriteNexusFile() method to create a complete
|
||||||
|
* NeXus file with all groups, datasets, and attributes.
|
||||||
|
*
|
||||||
|
* @param nxs Pointer to the PNeXus object containing the data to write
|
||||||
|
* @param outFileName Output filename for the NeXus HDF5 file
|
||||||
|
* @param debug If true, print additional debug information
|
||||||
|
*
|
||||||
|
* @note Currently only supports IDF version 2 files
|
||||||
|
*
|
||||||
|
* @see nxH5::PNeXus::WriteNexusFile()
|
||||||
|
*/
|
||||||
|
void h5nexus_writeTest(const nxH5::PNeXus *nxs, const std::string& outFileName, bool debug)
|
||||||
|
{
|
||||||
|
if (debug) {
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "++++++++++++++++++++" << std::endl;
|
||||||
|
std::cout << "Writing NeXus file" << std::endl;
|
||||||
|
std::cout << "++++++++++++++++++++" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxs->GetIdfVersion() == 1) {
|
||||||
|
std::cerr << "Error: IDF v1 write not yet implemented" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write using the read object's data
|
||||||
|
int result = const_cast<nxH5::PNeXus*>(nxs)->WriteNexusFile(outFileName, nxs->GetIdfVersion());
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
std::cout << "Successfully wrote: " << outFileName << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Failed to write file: " << outFileName << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write data from scratch
|
||||||
|
|
||||||
|
std::unique_ptr<nxH5::PNeXus> nxs_out = std::make_unique<nxH5::PNeXus>();
|
||||||
|
|
||||||
|
std::vector<int> ival;
|
||||||
|
std::vector<float> fval;
|
||||||
|
std::vector<std::string> sval;
|
||||||
|
|
||||||
|
H5::StrType strType(H5::PredType::C_S1, H5T_VARIABLE);
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
// raw_data_1
|
||||||
|
// ----------
|
||||||
|
|
||||||
|
// IDF version
|
||||||
|
ival.push_back(2);
|
||||||
|
nxs_out->AddDataset<int>("/raw_data_1/IDF_version", ival, {1}, H5::PredType::NATIVE_INT);
|
||||||
|
ival.clear();
|
||||||
|
|
||||||
|
// add group attribute to '/raw_data_1'
|
||||||
|
nxs_out->AddGroupAttribute("/raw_data_1", "NX_class", std::string("NXentry"));
|
||||||
|
|
||||||
|
// beamline
|
||||||
|
sval.push_back("piE3");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/beamline", sval, {1}, strType);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// definition
|
||||||
|
sval.push_back("muonTD");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/definition", sval, {1}, strType);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// run_number
|
||||||
|
ival.push_back(1234);
|
||||||
|
nxs_out->AddDataset<int>("/raw_data_1/run_number", ival, {1}, H5::PredType::NATIVE_INT);
|
||||||
|
ival.clear();
|
||||||
|
|
||||||
|
// title
|
||||||
|
sval.push_back("this is the run title.");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/title", sval, {1}, strType);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// start time
|
||||||
|
sval.push_back("2026-01-01T01:02:03");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/start_time", sval, {1}, strType);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// end time
|
||||||
|
sval.push_back("2026-01-01T02:03:42");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/end_time", sval, {1}, strType);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// experiment_identifier - pgroup for PSI
|
||||||
|
sval.push_back("p18324");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/experiment_identifier", sval, {1}, strType);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// -------------------
|
||||||
|
// detector_1 (NXdata)
|
||||||
|
// -------------------
|
||||||
|
|
||||||
|
// add group attribute to /raw_data_1/instrument
|
||||||
|
nxs_out->AddGroupAttribute("/raw_data_1/detector_1", "NX_class", std::string("NXdata"));
|
||||||
|
|
||||||
|
// counts
|
||||||
|
std::vector<int> counts(16*66000, 42); // data 16 histos with length 66000
|
||||||
|
nxs_out->AddDataset<int>("/raw_data_1/detector_1/counts", counts, {1, 16, 66000}, H5::PredType::NATIVE_INT);
|
||||||
|
|
||||||
|
// attributes for counts
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "signal", 1);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "axes", std::string("period_index,spectrum_index,raw_time"));
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "long_name", std::string("positron_counts"));
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "t0_bin", 2741);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "first_good_bin", 2741);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "last_good_bin", 66000);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "units", std::string("counts"));
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/detector_1/counts", "target", std::string("/raw_data_1/instrument/detector_1/counts"));
|
||||||
|
|
||||||
|
// raw_time
|
||||||
|
std::vector<float> raw_time(66000, 0.0);
|
||||||
|
for (unsigned int i=0; i<raw_time.size(); i++)
|
||||||
|
raw_time[i] = 0.1953125f*1.0e-3*((float)i-2741.0f+0.5f);
|
||||||
|
nxs_out->AddDataset<float>("/raw_data_1/detector_1/raw_time", raw_time, {66000}, H5::PredType::NATIVE_FLOAT);
|
||||||
|
|
||||||
|
// attributes raw_time
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/detector_1/raw_time", "units", std::string("microseconds"));
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/detector_1/raw_time", "target", std::string("/raw_data_1/instrument/detector_1/raw_time"));
|
||||||
|
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
// instrument
|
||||||
|
// ----------
|
||||||
|
|
||||||
|
// add group attribute to /raw_data_1/instrument
|
||||||
|
nxs_out->AddGroupAttribute("/raw_data_1/instrument", "NX_class", std::string("NXinstrument"));
|
||||||
|
|
||||||
|
// name
|
||||||
|
sval.push_back("LEM");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/instrument/name", sval, {1}, strType);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// ------
|
||||||
|
// source
|
||||||
|
// ------
|
||||||
|
|
||||||
|
// add group attribute to /raw_data_1/instrument/source
|
||||||
|
nxs_out->AddGroupAttribute("/raw_data_1/instrument/source", "NX_class", std::string("NXsource"));
|
||||||
|
|
||||||
|
// name
|
||||||
|
sval.push_back("PSI");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/instrument/source/name", sval, {1}, strType);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// type
|
||||||
|
sval.push_back("continuous muon source");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/instrument/source/types", sval, {1}, strType);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// probe
|
||||||
|
sval.push_back("postive muons");
|
||||||
|
nxs_out->AddDataset<std::string>("/raw_data_1/instrument/source/probe", sval, {1}, strType);
|
||||||
|
sval.clear();
|
||||||
|
|
||||||
|
// -----------------------
|
||||||
|
// detector_1 (NXdetector)
|
||||||
|
// -----------------------
|
||||||
|
|
||||||
|
// add group attribute to /raw_data_1/instrument/detector_1
|
||||||
|
nxs_out->AddGroupAttribute("/raw_data_1/instrument/detector_1", "NX_class", std::string("NXdetector"));
|
||||||
|
|
||||||
|
// counts
|
||||||
|
nxs_out->AddDataset<int>("/raw_data_1/instrument/detector_1/counts", counts, {1, 16, 66000}, H5::PredType::NATIVE_INT);
|
||||||
|
|
||||||
|
// attributes for counts
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "signal", 1);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "axes", std::string("period_index,spectrum_index,raw_time"));
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "long_name", std::string("positron_counts"));
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "t0_bin", 2741);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "first_good_bin", 2741);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "last_good_bin", 66000);
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "units", std::string("counts"));
|
||||||
|
nxs_out->AddDatasetAttribute<int>("/raw_data_1/instrument/detector_1/counts", "target", std::string("/raw_data_1/instrument/detector_1/counts"));
|
||||||
|
|
||||||
|
// raw_time
|
||||||
|
nxs_out->AddDataset<float>("/raw_data_1/instrument/detector_1/raw_time", raw_time, {66000}, H5::PredType::NATIVE_FLOAT);
|
||||||
|
|
||||||
|
// attributes raw_time
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/instrument/detector_1/raw_time", "units", std::string("microseconds"));
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/instrument/detector_1/raw_time", "target", std::string("/raw_data_1/instrument/detector_1/raw_time"));
|
||||||
|
|
||||||
|
// resolution
|
||||||
|
fval.push_back(195.3125);
|
||||||
|
nxs_out->AddDataset<float>("/raw_data_1/instrument/detector_1/resolution", fval, {1}, H5::PredType::NATIVE_FLOAT);
|
||||||
|
fval.clear();
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/instrument/detector_1/resolution",
|
||||||
|
"units", std::string("picoseconds"));
|
||||||
|
|
||||||
|
// spectrum_index
|
||||||
|
for (unsigned int i=0; i<66000; i++)
|
||||||
|
ival.push_back(i+1);
|
||||||
|
nxs_out->AddDataset<int>("/raw_data_1/instrument/detector_1/spectrum_index", ival, {66000}, H5::PredType::NATIVE_FLOAT);
|
||||||
|
ival.clear();
|
||||||
|
|
||||||
|
// dead_time
|
||||||
|
std::vector<float> deadTime(66000, 0.0);
|
||||||
|
nxs_out->AddDataset<float>("/raw_data_1/instrument/detector_1/dead_time", deadTime, {66000}, H5::PredType::NATIVE_FLOAT);
|
||||||
|
|
||||||
|
// attributes dead_time
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/instrument/detector_1/dead_time", "available", 0);
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/instrument/detector_1/dead_time", "units", std::string("microseconds"));
|
||||||
|
nxs_out->AddDatasetAttribute<float>("/raw_data_1/instrument/detector_1/dead_time", "target", std::string("/raw_data_1/instrument/detector_1/dead_time"));
|
||||||
|
|
||||||
|
// add root attributes
|
||||||
|
// file name
|
||||||
|
nxs_out->AddRootAttribute("file_name", std::string("_test.nxs"));
|
||||||
|
// date-time
|
||||||
|
std::time_t time = std::time({});
|
||||||
|
char timeString[std::size("yyyy-mm-ddThh:mm:ssZ")];
|
||||||
|
std::strftime(std::data(timeString), std::size(timeString),
|
||||||
|
"%FT%TZ", std::gmtime(&time));
|
||||||
|
nxs_out->AddRootAttribute("file_time", std::string(timeString));
|
||||||
|
// NeXus version
|
||||||
|
nxs_out->AddRootAttribute("NeXus_Version", std::string("4.3.0"));
|
||||||
|
// hdf5 version
|
||||||
|
nxs_out->AddRootAttribute("HDF5_Version", std::string(nxs->GetHdf5Version()));
|
||||||
|
// creator
|
||||||
|
nxs_out->AddRootAttribute("creator", std::string("h5nexus - PSI"));
|
||||||
|
|
||||||
|
nxs_out->WriteNexusFile("_test.nxs");
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* @brief Main entry point for the h5nexus program
|
||||||
|
*
|
||||||
|
* Parses command-line arguments and performs the requested operations:
|
||||||
|
* - Read and display NeXus HDF5 file information
|
||||||
|
* - Write NeXus HDF5 files with modified data
|
||||||
|
* - Calculate dead time corrections
|
||||||
|
*
|
||||||
|
* @param argc Number of command-line arguments
|
||||||
|
* @param argv Array of command-line argument strings
|
||||||
|
*
|
||||||
|
* @return 0 on success, non-zero on error
|
||||||
|
*
|
||||||
|
* @see h5nexus_syntax() for available command-line options
|
||||||
|
*/
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
std::string fileName{""};
|
||||||
|
std::string fileNameOut{""};
|
||||||
|
std::string dataNameOut{""};
|
||||||
|
int idx{-1};
|
||||||
|
bool printDebug{false};
|
||||||
|
bool deadTimeEstimate{false};
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
h5nexus_syntax();
|
||||||
|
|
||||||
|
for (int i=1; i<argc; i++) {
|
||||||
|
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
|
||||||
|
h5nexus_syntax();
|
||||||
|
} else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#ifdef HAVE_GIT_REV_H
|
||||||
|
std::cout << std::endl << "h5nexus version: " << PACKAGE_VERSION << ", git-branch: " << GIT_BRANCH << ", git-rev: " << GIT_CURRENT_SHA1 << " (" << BUILD_TYPE << ")" << std::endl << std::endl;
|
||||||
|
#else
|
||||||
|
std::cout << std::endl << "h5nexus version: " << PACKAGE_VERSION << " (" << BUILD_TYPE << ")" << std::endl << std::endl;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_GIT_REV_H
|
||||||
|
std::cout << std::endl << "h5nexus git-branch: " << GIT_BRANCH << ", git-rev: " << GIT_CURRENT_SHA1 << std::endl << std::endl;
|
||||||
|
#else
|
||||||
|
std::cout << std::endl << "h5nexus version: unkown." << std::endl << std::endl;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
} else if (!strcmp(argv[i], "--fn")) {
|
||||||
|
if (i+1 >= argc) {
|
||||||
|
std::cout << std::endl << "**ERROR** found --fn without <fln>." << std::endl;
|
||||||
|
h5nexus_syntax();
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
fileName = argv[i];
|
||||||
|
} else if (!strcmp(argv[i], "-dt") || !strcmp(argv[i], "--dead_time_estimate")) {
|
||||||
|
deadTimeEstimate = true;
|
||||||
|
} else if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) {
|
||||||
|
printDebug = true;
|
||||||
|
} else if (!strcmp(argv[i], "--data")) {
|
||||||
|
if (i+2 >= argc) {
|
||||||
|
std::cout << std::endl << "**ERROR** in --data idx <dout>." << std::endl;
|
||||||
|
h5nexus_syntax();
|
||||||
|
}
|
||||||
|
int ii;
|
||||||
|
try {
|
||||||
|
ii = std::stoi(argv[i+1]);
|
||||||
|
} catch (const std::invalid_argument& ia) {
|
||||||
|
std::cout << std::endl << "**ERROR** couldn't convert idx from arguments given." << std::endl;
|
||||||
|
h5nexus_syntax();
|
||||||
|
}
|
||||||
|
if (ii < 0) {
|
||||||
|
std::cout << std::endl << "**ERROR** found idx < 0, namely " << ii << std::endl;
|
||||||
|
h5nexus_syntax();
|
||||||
|
}
|
||||||
|
idx = ii;
|
||||||
|
dataNameOut = argv[i+2];
|
||||||
|
i += 2;
|
||||||
|
} else if (!strcmp(argv[i], "--out")) {
|
||||||
|
if (i+1 >= argc) {
|
||||||
|
std::cout << std::endl << "**ERROR** found --out without <fout>." << std::endl;
|
||||||
|
h5nexus_syntax();
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
fileNameOut = argv[i];
|
||||||
|
} else {
|
||||||
|
h5nexus_syntax();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileName.empty()) {
|
||||||
|
std::cerr << std::endl;
|
||||||
|
std::cerr << "**ERROR** <fln> is missing." << std::endl;
|
||||||
|
std::cerr << std::endl;
|
||||||
|
h5nexus_syntax();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printDebug) {
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << ">> fln = '" << fileName << "'" << std::endl;
|
||||||
|
std::cout << ">> fout = '" << fileNameOut << "'" << std::endl;
|
||||||
|
std::cout << ">> dout = '" << dataNameOut << "', idx=" << idx << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<nxH5::PNeXus> nxs = std::make_unique<nxH5::PNeXus>(fileName, printDebug);
|
||||||
|
|
||||||
|
nxs->Dump();
|
||||||
|
|
||||||
|
std::vector<float> dte;
|
||||||
|
if (deadTimeEstimate) {
|
||||||
|
dte = h5nexus_deadTimeEstimate(nxs.get(), printDebug);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileNameOut.empty()) {
|
||||||
|
h5nexus_writeTest(nxs.get(), fileNameOut, printDebug);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dataNameOut.empty()) {
|
||||||
|
h5nexus_writeData(nxs.get(), fileName, dataNameOut, idx, dte);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
src/external/nexus/nexus_definitions/NeXus-Def-V2-Rev10.pdf
vendored
Normal file
BIN
src/external/nexus/nexus_definitions/NeXus-Def-V2-Rev10.pdf
vendored
Normal file
Binary file not shown.
Reference in New Issue
Block a user