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