31 Commits

Author SHA1 Message Date
AndreaRigoni
b64afe8773 add documention workflow 2026-03-06 10:45:33 +00:00
AndreaRigoni
f3ebba4931 add thrust 2026-03-06 10:45:14 +00:00
AndreaRigoni
79e1abb2ff add USE_CUDA env in python_build 2026-03-05 15:17:30 +00:00
AndreaRigoni
554eff9b55 add filters in python bindings 2026-03-05 15:03:19 +00:00
AndreaRigoni
42db99759f fix py dense 2026-03-05 14:26:05 +00:00
AndreaRigoni
69920acd61 poetry python build 2026-03-05 12:42:14 +00:00
AndreaRigoni
647d0caa1c feat: Add Python packaging infrastructure and comprehensive bindings for math and vector types. 2026-03-05 11:39:27 +00:00
AndreaRigoni
e69b29a259 add first python bindings 2026-03-05 09:16:15 +00:00
AndreaRigoni
9a59e031ed feat: Implement a custom MetaAllocator for uLib::Vector to enable GPU memory management and integrate CUDA support into the build system. 2026-03-04 20:52:01 +00:00
AndreaRigoni
adedbcc37c feat: add CUDA raytracing benchmark and refactor VoxRaytracer::RayData to use DataAllocator for host/device memory management. 2026-03-04 17:47:18 +00:00
AndreaRigoni
eb76521060 add clangd linting fix 2026-03-04 14:37:02 +00:00
AndreaRigoni
b1fb123026 feat: Implement CUDA support for VoxRaytracer, add CUDA tests for voxel image operations, and update CMake to enable CUDA compilation. 2026-03-04 13:59:45 +00:00
AndreaRigoni
52580d8cde refactor: migrate voxel data storage to DataAllocator for CUDA 2026-02-28 10:05:39 +00:00
AndreaRigoni
07915295cb feat: fix signaling and implement a ping-pong signal/slot test 2026-02-28 08:58:04 +00:00
AndreaRigoni
d56758d0b3 refactor: Update CMake build system and streamline Core object serialization and property handling. 2026-02-21 16:16:28 +00:00
AndreaRigoni
7ded15d596 chore: remove LTK, MOC, and QVTKViewport2 components. 2026-02-21 15:40:21 +00:00
AndreaRigoni
c04722c2bb refactor: reformat type introspection code and remove ObjectProps system. 2026-02-21 10:45:25 +00:00
AndreaRigoni
8566ceb662 feat: add condaenv.yml for environment setup and update README.md with detailed build instructions. 2026-02-20 18:05:40 +00:00
AndreaRigoni
5ae2e106ab added conanfile 2026-02-20 17:27:30 +00:00
c526f61f8c Merge pull request #3 from OpenCMT/andrea-dev
fix mismatch Origin - Position
2025-09-25 17:38:45 +02:00
AndreaRigoni
54997fe0ac fix mismatch Origin - Position 2025-09-25 17:34:23 +02:00
94bad596ed Merge pull request #2 from OpenCMT/andrea-dev
fix export to Vti
2025-09-23 18:52:54 +02:00
AndreaRigoni
fc909da400 fix export to Vti 2025-09-23 18:21:11 +02:00
b0240dc807 Merge pull request #1 from OpenCMT/andrea-dev
Andrea dev
2025-09-18 13:12:12 +02:00
AndreaRigoni
591cc9d8bc add version 0.6 - make external build possible 2025-09-05 18:04:54 +02:00
AndreaRigoni
2e401f6fc5 add posibility to compile in build directory 2025-09-04 16:12:38 +02:00
AndreaRigoni
91abd56587 fix Root needs for C++17 2025-09-04 16:11:57 +02:00
AndreaRigoni
01ff8a0a0d update 2025-09-02 13:01:55 +02:00
AndreaRigoni
b86e27a9c4 add VTK save early 2025-09-02 12:42:46 +02:00
Paolo Andreetto
820730bc84 New root dicts 2023-09-01 14:14:06 +02:00
Paolo Andreetto
06c363ab8c Workaround for CentOS7 2023-04-04 16:31:30 +02:00
147 changed files with 8629 additions and 8822 deletions

52
.clangd Normal file
View File

@@ -0,0 +1,52 @@
CompileFlags:
CompilationDatabase: build
Add:
- -I/home/rigoni/devel/cmt/ulib/src
- -isystem/home/share/micromamba/envs/mutom/include
- -isystem/home/share/micromamba/envs/mutom/include/eigen3
- -isystem/home/share/micromamba/envs/mutom/targets/x86_64-linux/include
- -isystem/home/share/micromamba/envs/mutom/lib/gcc/x86_64-conda-linux-gnu/14.3.0/include/c++
- -isystem/isystem/home/share/micromamba/envs/mutom/lib/gcc/x86_64-conda-linux-gnu/14.3.0/include/c++/x86_64-conda-linux-gnu
- -isystem/home/share/micromamba/envs/mutom/x86_64-conda-linux-gnu/sysroot/usr/include
- "--gcc-toolchain=/home/share/micromamba/envs/mutom"
- -D_ULIB_DETAIL_SIGNAL_EMIT
- -DUSE_CUDA
- -std=c++17
- "-D__host__="
- "-D__device__="
- "-D__global__="
- "-D__constant__="
- "-D__shared__="
- "-D__align__(x)="
- "-D__forceinline__=inline"
- "-D__launch_bounds__(x)="
Diagnostics:
UnusedIncludes: None
MissingIncludes: None
---
If:
PathExclude: [/home/rigoni/devel/cmt/ulib/src/.*]
Diagnostics:
Suppress: ["*"]
---
If:
PathMatch: [.*\.cu, .*/src/Math/testing/VoxRaytracerTest.cpp, .*/src/Math/VoxRaytracer.cpp, .*/src/Math/VoxImage.cpp]
CompileFlags:
Add:
- "-x"
- "cuda"
- "--cuda-path=/home/share/micromamba/envs/mutom"
- "--cuda-gpu-arch=sm_61"
- "--gcc-toolchain=/home/share/micromamba/envs/mutom"
- "-L/home/share/micromamba/envs/mutom/lib"
- "-lcudart"
- "-lcuda"
- "-U__host__"
- "-U__device__"
- "-U__global__"
- "-U__constant__"
- "-U__shared__"
- "-U__forceinline__"

View File

@@ -0,0 +1,41 @@
name: MkDocs Subpath Deploy
on:
push:
branches:
- andrea-dev # Trigger on main branch
jobs:
build-and-deploy:
runs-on: mildpub # Runner that can access to SSH_YFINPUB_HOST
steps:
- name: Checkout del codice
uses: actions/checkout@v4
- name: Configura Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Installa dipendenze
run: |
python -m pip install --upgrade pip
pip install mkdocs-material
pip install -r requirements.txt
- name: Build del sito
run: mkdocs build
- name: Deploy via SSH (SCP)
uses: https://github.com/appleboy/scp-action@master
with:
host: ${{ vars.SSH_YFINPUB_HOST }}
username: ${{ vars.SSH_YFINPUB_USER }}
key: ${{ secrets.MILD_PUB }}
port: 22
source: "site/*"
# Il percorso sul server deve corrispondere alla tua sottopagina
target: "/var/www/docs/cmt/uLib/"
strip_components: 1 # Rimuove la cartella "site/" e mette solo il contenuto
rm: true # Pulisce la cartella prima di copiare (opzionale, stile Vercel)

12
.gitignore vendored
View File

@@ -1,3 +1,15 @@
CMakeFiles/ CMakeFiles/
build/ build/
.cache/
build_warnings*.log
final_build.log
cmake_configure.log
compile_commands.json
dist/
build_python/
src/Python/uLib/*.so*
src/Python/uLib/*.pyd
src/Python/uLib/*.pyc
src/Python/uLib/__pycache__
src/Python/uLib/.nfs*

32
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,32 @@
{
"clangd.fallbackFlags": [
"-I/home/rigoni/devel/cmt/ulib/src",
"-isystem/home/share/micromamba/envs/mutom/include",
"-isystem/home/share/micromamba/envs/mutom/include/eigen3",
"-isystem/home/share/micromamba/envs/mutom/targets/x86_64-linux/include",
"-isystem/home/share/micromamba/envs/mutom/lib/gcc/x86_64-conda-linux-gnu/14.3.0/include/c++",
"-isystem/home/share/micromamba/envs/mutom/lib/gcc/x86_64-conda-linux-gnu/14.3.0/include/c++/x86_64-conda-linux-gnu",
"-isystem/home/share/micromamba/envs/mutom/x86_64-conda-linux-gnu/sysroot/usr/include",
"--gcc-toolchain=/home/share/micromamba/envs/mutom",
"-D__host__=",
"-D__device__=",
"-D__global__=",
"-D__constant__=",
"-D__shared__=",
"-DUSE_CUDA",
"-D__CUDACC__"
],
"clangd.semanticHighlighting.enable": true,
"clangd.arguments": [
"--compile-commands-dir=build",
"--query-driver=/home/share/micromamba/envs/mutom/bin/g++,/home/share/micromamba/envs/mutom/bin/gcc,/home/share/micromamba/envs/mutom/bin/nvcc",
"--suppress-system-warnings",
"--all-scopes-completion",
"--completion-style=detailed",
"--header-insertion=never",
"-j=4",
"--pch-storage=memory",
"--background-index",
"--log=verbose"
]
}

View File

@@ -15,16 +15,16 @@ set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin CACHE PATH "build path for
mark_as_advanced(EXECUTABLE_OUTPUT_PATH) mark_as_advanced(EXECUTABLE_OUTPUT_PATH)
## Install directories ## ## Install directories ##
set(PACKAGE_INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables") set(INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables")
set(PACKAGE_INSTALL_LIB_DIR lib/${PACKAGE_NAME} CACHE PATH "Installation directory for libraries") set(INSTALL_LIB_DIR lib/${PACKAGE_NAME} CACHE PATH "Installation directory for libraries")
set(PACKAGE_INSTALL_INC_DIR include/${PACKAGE_NAME} CACHE PATH "Installation directory for headers") set(INSTALL_INC_DIR include/${PACKAGE_NAME} CACHE PATH "Installation directory for headers")
set(PACKAGE_INSTALL_DATA_DIR share/${PACKAGE_NAME} CACHE PATH "Installation directory for data files") set(INSTALL_DATA_DIR share/${PACKAGE_NAME} CACHE PATH "Installation directory for data files")
if(WIN32 AND NOT CYGWIN) if(WIN32 AND NOT CYGWIN)
set(DEF_INSTALL_CMAKE_DIR CMake) set(DEF_INSTALL_CMAKE_DIR CMake)
else() else()
set(DEF_INSTALL_CMAKE_DIR lib/cmake/${PACKAGE_NAME}) set(DEF_INSTALL_CMAKE_DIR lib/cmake/${PACKAGE_NAME})
endif() endif()
set(PACKAGE_INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files")
# Make relative paths absolute (needed later on) # Make relative paths absolute (needed later on)
foreach(p LIB BIN INC DATA CMAKE) foreach(p LIB BIN INC DATA CMAKE)
@@ -58,7 +58,7 @@ endif()
set(CMAKE_CXX_WARNING_OPTION "" CACHE STRING "Warning level -WAll to verbose all warnings") set(CMAKE_CXX_WARNING_OPTION "" CACHE STRING "Warning level -WAll to verbose all warnings")
set(CMAKE_VERBOSE_MAKEFILE FALSE CACHE STRING "Verbose compile output switch") set(CMAKE_VERBOSE_MAKEFILE FALSE CACHE STRING "Verbose compile output switch")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x ${CMAKE_CXX_WARNING_OPTION}") # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x ${CMAKE_CXX_WARNING_OPTION}")

View File

@@ -41,15 +41,15 @@ macro(uLib_add_shared_library name)
install(TARGETS ${mname} install(TARGETS ${mname}
EXPORT "${PROJECT_NAME}Targets" EXPORT "${PROJECT_NAME}Targets"
RUNTIME DESTINATION ${PACKAGE_INSTALL_BIN_DIR} COMPONENT bin RUNTIME DESTINATION ${INSTALL_BIN_DIR} COMPONENT bin
LIBRARY DESTINATION ${PACKAGE_INSTALL_LIB_DIR} COMPONENT lib LIBRARY DESTINATION ${INSTALL_LIB_DIR} COMPONENT lib
# PUBLIC_HEADER DESTINATION ${PACKAGE_INSTALL_INC_DIR} COMPONENT dev # PUBLIC_HEADER DESTINATION ${INSTALL_INC_DIR} COMPONENT dev
) )
endif(SOURCES) endif(SOURCES)
if(HEADERS) if(HEADERS)
foreach(header ${HEADERS}) foreach(header ${HEADERS})
install(FILES ${header} DESTINATION ${PACKAGE_INSTALL_INC_DIR}/${name}) install(FILES ${header} DESTINATION ${INSTALL_INC_DIR}/${name})
endforeach(header) endforeach(header)
endif(HEADERS) endif(HEADERS)
@@ -70,7 +70,7 @@ macro(uLib_add_target name)
install(TARGETS ${name} install(TARGETS ${name}
EXPORT "${PROJECT_NAME}Targets" EXPORT "${PROJECT_NAME}Targets"
RUNTIME DESTINATION ${PACKAGE_INSTALL_BIN_DIR} COMPONENT bin RUNTIME DESTINATION ${INSTALL_BIN_DIR} COMPONENT bin
) )
ENDMACRO(uLib_add_target) ENDMACRO(uLib_add_target)
@@ -82,7 +82,7 @@ ENDMACRO(uLib_add_target)
# TESTS and LIBRARIES must be defined # TESTS and LIBRARIES must be defined
macro(uLib_add_tests name) macro(uLib_add_tests name)
foreach(tn ${TESTS}) foreach(tn ${TESTS})
add_executable(${tn} EXCLUDE_FROM_ALL ${tn}.cpp) add_executable(${tn} ${tn}.cpp)
add_test(NAME ${tn} COMMAND ${tn}) add_test(NAME ${tn} COMMAND ${tn})
target_link_libraries(${tn} ${LIBRARIES}) target_link_libraries(${tn} ${LIBRARIES})
@@ -91,7 +91,9 @@ macro(uLib_add_tests name)
# custom target to compile all tests # custom target to compile all tests
add_custom_target(all-${name}-tests) add_custom_target(all-${name}-tests)
add_dependencies(all-${name}-tests ${TESTS}) if(TESTS)
add_dependencies(all-${name}-tests ${TESTS})
endif()
endmacro(uLib_add_tests name) endmacro(uLib_add_tests name)

View File

@@ -3,15 +3,35 @@
##### CMAKE LISTS ############################################################## ##### CMAKE LISTS ##############################################################
################################################################################ ################################################################################
cmake_minimum_required (VERSION 2.6) cmake_minimum_required (VERSION 3.26)
if(POLICY CMP0167)
cmake_policy(SET CMP0167 NEW)
endif()
## -------------------------------------------------------------------------- ## ## -------------------------------------------------------------------------- ##
project(uLib) project(uLib)
# CUDA Toolkit seems to be missing locally. Toggle ON if nvcc is made available.
option(USE_CUDA "Enable CUDA support" ON)
if(USE_CUDA)
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -allow-unsupported-compiler")
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr")
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Wno-deprecated-gpu-targets")
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe \"--diag_suppress=20012\"")
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe \"--diag_suppress=20014\"")
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe \"--diag_suppress=20015\"")
find_package(CUDAToolkit REQUIRED)
enable_language(CUDA)
set(CMAKE_CUDA_ARCHITECTURES 61)
include_directories(${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
add_compile_definitions(USE_CUDA)
endif()
# The version number. # The version number.
set(PROJECT_VERSION_MAJOR 0) set(PROJECT_VERSION_MAJOR 0)
set(PROJECT_VERSION_MINOR 5) set(PROJECT_VERSION_MINOR 6)
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}") set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
set(PROJECT_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}") set(PROJECT_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
@@ -33,19 +53,31 @@ message(STATUS "Module path = ${CMAKE_MODULE_PATH}")
## GLOBALS ------------------------------------------------------------------ ## ## GLOBALS ------------------------------------------------------------------ ##
set(PACKAGE_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/bin # -- move to GnuInstallDirs
CACHE PATH "Installation directory for executables") # ref: https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html
set(PACKAGE_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/lib/ include(GNUInstallDirs)
CACHE PATH "Installation directory for libraries") set(INSTALL_INC_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${PACKAGE_NAME}
set(PACKAGE_INSTALL_INC_DIR ${CMAKE_INSTALL_PREFIX}/include/${PACKAGE_NAME} CACHE PATH "Location of header files (.../include)" )
CACHE PATH "Installation directory for headers") set(INSTALL_ETC_DIR ${CMAKE_INSTALL_SYSCONFDIR}/${PACKAGE_NAME}
set(PACKAGE_INSTALL_DATA_DIR ${CMAKE_INSTALL_PREFIX}/share/${PACKAGE_NAME} CACHE PATH "Location of configuration files (.../etc)" )
CACHE PATH "Installation directory for data files") set(INSTALL_BIN_DIR ${CMAKE_INSTALL_BINDIR}/${PACKAGE_NAME}
set(PACKAGE_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_PREFIX}/lib/cmake/${PACKAGE_NAME} CACHE PATH "Location of executable files (.../bin)" )
CACHE PATH "Installation directory for CMake files") set(INSTALL_LIB_DIR ${CMAKE_INSTALL_LIBDIR}
CACHE PATH "Location of library files (.../lib)" )
set(INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PACKAGE_NAME}
CACHE PATH "Location of cmake files (.../lib/cmake)" )
set(INSTALL_DATA_DIR ${CMAKE_INSTALL_DATADIR}/${PACKAGE_NAME}
CACHE PATH "Location of data files (.../share)" )
set(SRC_DIR ${PROJECT_SOURCE_DIR}/src) set(SRC_DIR ${PROJECT_SOURCE_DIR}/src)
# this is used to be exported in build target
# ( to compile against build directory instead of install )
set(ULIB_SOURCE_DIR ${PROJECT_SOURCE_DIR})
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Release' as none was specified.") message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
@@ -60,44 +92,62 @@ set(CMAKE_CXX_WARNING_OPTION ""
set(CMAKE_VERBOSE_MAKEFILE FALSE set(CMAKE_VERBOSE_MAKEFILE FALSE
CACHE STRING "Verbose compile output switch") CACHE STRING "Verbose compile output switch")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x ${CMAKE_CXX_WARNING_OPTION}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_WARNING_OPTION}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -UULIB_SERIALIZATION_ON") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -UULIB_SERIALIZATION_ON -Wno-cpp")
# CTEST framework
include(CTest)
enable_testing()
#enable_testing()
## FIND PACKAGES ------------------------------------------------------------ ## ## FIND PACKAGES ------------------------------------------------------------ ##
set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON) set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF) set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.45.0 COMPONENTS program_options REQUIRED) message(STATUS "CMAKE_PREFIX_PATH is ${CMAKE_PREFIX_PATH}")
find_package(Boost 1.45.0 COMPONENTS program_options serialization unit_test_framework REQUIRED)
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
find_package(Eigen3 CONFIG REQUIRED) find_package(Eigen3 CONFIG REQUIRED)
include(${EIGEN3_USE_FILE}) get_target_property(EIGEN3_INCLUDE_DIRS Eigen3::Eigen INTERFACE_INCLUDE_DIRECTORIES)
include_directories(${EIGEN3_INCLUDE_DIRS})
find_package(ROOT CONFIG REQUIRED) find_package(ROOT CONFIG REQUIRED)
include(${ROOT_USE_FILE}) include(${ROOT_USE_FILE})
find_package(VTK REQUIRED find_package(VTK REQUIRED)
COMPONENTS CommonColor # include(${VTK_USE_FILE})
CommonCore
FiltersCore find_package(pybind11 REQUIRED)
FiltersModeling
FiltersSources
IOLegacy option(CENTOS_SUPPORT "VTK definitions for CentOS" OFF)
IOXML if(CENTOS_SUPPORT)
IOXMLParser find_package(VTK CONFIG REQUIRED)
ImagingCore include(${VTK_USE_FILE})
InteractionStyle else()
InteractionWidgets find_package(VTK REQUIRED
RenderingAnnotation COMPONENTS CommonColor
RenderingContextOpenGL2 CommonCore
RenderingCore FiltersCore
RenderingFreeType FiltersModeling
RenderingGL2PSOpenGL2 FiltersSources
RenderingOpenGL2 IOLegacy
RenderingVolumeOpenGL2) IOXML
IOXMLParser
ImagingCore
InteractionStyle
InteractionWidgets
RenderingAnnotation
RenderingContextOpenGL2
RenderingCore
RenderingFreeType
RenderingGL2PSOpenGL2
RenderingOpenGL2
RenderingVolumeOpenGL2)
endif()
set(CMAKE_REQUIRED_INCLUDES CMAKE_REQUIRED_INCLUDES math.h) set(CMAKE_REQUIRED_INCLUDES CMAKE_REQUIRED_INCLUDES math.h)
set(CMAKE_REQUIRED_LIBRARIES CMAKE_REQUIRED_LIBRARIES m) set(CMAKE_REQUIRED_LIBRARIES CMAKE_REQUIRED_LIBRARIES m)
@@ -136,7 +186,7 @@ configure_file("${PROJECT_SOURCE_DIR}/CMakeConfig.in.h"
"${PROJECT_BINARY_DIR}/config.h") "${PROJECT_BINARY_DIR}/config.h")
install(FILES "${PROJECT_BINARY_DIR}/config.h" install(FILES "${PROJECT_BINARY_DIR}/config.h"
DESTINATION ${PACKAGE_INSTALL_INC_DIR}) DESTINATION ${INSTALL_INC_DIR})
## ADD LIBRARIES SUBDIRECTORIES --------------------------------------------- ## ## ADD LIBRARIES SUBDIRECTORIES --------------------------------------------- ##
@@ -163,6 +213,8 @@ add_subdirectory(${SRC_DIR}/Root)
include_directories(${SRC_DIR}/Vtk) include_directories(${SRC_DIR}/Vtk)
add_subdirectory(${SRC_DIR}/Vtk) add_subdirectory(${SRC_DIR}/Vtk)
add_subdirectory(${SRC_DIR}/Python)
#add_subdirectory("${SRC_DIR}/utils/make_recipe") #add_subdirectory("${SRC_DIR}/utils/make_recipe")
## Documentation and packages ## Documentation and packages
@@ -181,8 +233,8 @@ add_subdirectory(${SRC_DIR}/Vtk)
# Create the FooBarConfig.cmake and FooBarConfigVersion files # Create the FooBarConfig.cmake and FooBarConfigVersion files
file(RELATIVE_PATH REL_INCLUDE_DIR "${PACKAGE_INSTALL_CMAKE_DIR}" # file(RELATIVE_PATH REL_INCLUDE_DIR "${INSTALL_CMAKE_DIR}"
"${PACKAGE_INSTALL_INC_DIR}") # "${INSTALL_INC_DIR}")
# ... for the build tree # ... for the build tree
#set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}") #set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}")
@@ -191,21 +243,53 @@ file(RELATIVE_PATH REL_INCLUDE_DIR "${PACKAGE_INSTALL_CMAKE_DIR}"
# ... for the install tree # ... for the install tree
set(CONF_INCLUDE_DIRS "\${ULIB_CMAKE_DIR}/${REL_INCLUDE_DIR}") set(CONF_INCLUDE_DIRS "\${ULIB_CMAKE_DIR}/${REL_INCLUDE_DIR}")
configure_file(uLibConfig.cmake.in # [ removed for the configure_config_file ]
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/uLibConfig.cmake" # configure_file(uLibConfig.cmake.in
@ONLY) # "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/uLibConfig.cmake"
# @ONLY)
# ... for both # ... for both
configure_file(uLibConfigVersion.cmake.in configure_file(uLibConfigVersion.cmake.in
"${PROJECT_BINARY_DIR}/uLibConfigVersion.cmake" @ONLY) "${PROJECT_BINARY_DIR}/uLibConfigVersion.cmake" @ONLY)
install(FILES "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/uLibConfig.cmake"
# from CMake 3.x configure file shall be created using a dedicated function
# see: https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html
#
include(CMakePackageConfigHelpers)
configure_package_config_file(uLibConfig.cmake.in
"${PROJECT_BINARY_DIR}/uLibConfig.cmake"
INSTALL_DESTINATION ${INSTALL_CMAKE_DIR}
PATH_VARS
INSTALL_LIB_DIR
INSTALL_INC_DIR
INSTALL_BIN_DIR
INSTALL_CMAKE_DIR
INSTALL_ETC_DIR
INSTALL_DATA_DIR
ULIB_SOURCE_DIR
ULIB_SHARED_LIBRARIES
# NO_SET_AND_CHECK_MACRO
# NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
install(FILES "${PROJECT_BINARY_DIR}/uLibConfig.cmake"
"${PROJECT_BINARY_DIR}/uLibConfigVersion.cmake" "${PROJECT_BINARY_DIR}/uLibConfigVersion.cmake"
DESTINATION "${PACKAGE_INSTALL_CMAKE_DIR}" DESTINATION "${INSTALL_CMAKE_DIR}"
COMPONENT dev) COMPONENT dev)
# this is a special target file for the build tree
# it is used also to identify if we are using a build direcory
# to link a project against uLib. see: uLibConfig.cmake ( IF )
export (TARGETS ${ULIB_SHARED_LIBRARIES}
FILE "${PROJECT_BINARY_DIR}/uLibTargets-build.cmake"
# NAMESPACE "uLib::"
)
# Install the export set for use with the install-tree # Install the export set for use with the install-tree
install(EXPORT "${PROJECT_NAME}Targets" install(EXPORT "uLibTargets"
DESTINATION "${PACKAGE_INSTALL_CMAKE_DIR}" FILE "uLibTargets.cmake"
DESTINATION "${INSTALL_CMAKE_DIR}"
COMPONENT dev) COMPONENT dev)

16
CMakePresets.json Normal file
View File

@@ -0,0 +1,16 @@
{
"version": 8,
"configurePresets": [
{
"name": "andrea",
"displayName": "Custom configure preset",
"description": "Sets Ninja generator, build and install directory",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
}
}
]
}

9
CMakeUserPresets.json Normal file
View File

@@ -0,0 +1,9 @@
{
"version": 4,
"vendor": {
"conan": {}
},
"include": [
"build/CMakePresets.json"
]
}

View File

@@ -7,3 +7,64 @@ base toolkit library
CMT Cosmic Muon Tomography reconstruction, analysis and imaging software CMT Cosmic Muon Tomography reconstruction, analysis and imaging software
Developed by University of Padova and INFN Sezione di Padova Italy Developed by University of Padova and INFN Sezione di Padova Italy
## Build Instructions
This project relies on `conan` (v2) for dependency management (Eigen3, Boost) and `cmake` for configuration. VTK is provided through the micromamba/conda-forge environment.
### Prerequisites
This project requires a `conda` or `micromamba` environment containing the necessary global tools like **ROOT**, **VTK**, and **Conan** (v2). We provide a `condaenv.yml` file to quickly build this environment.
#### Installing Micromamba (Optional)
If you do not have `conda` installed, `micromamba` is a fast and lightweight alternative. You can install it on Linux via:
```bash
"${SHELL}" <(curl -L micro.mamba.pm/install.sh)
```
#### Creating the Environment
You can create and activate the environment using either `micromamba` or `conda`.
**Using Micromamba:**
```bash
micromamba env create -f condaenv.yml
micromamba activate mutom
```
**Using Conda:**
```bash
conda env create -f condaenv.yml
conda activate mutom
```
### Configure and Build
1. **Configure Conan profile (if you haven't yet on your machine):**
```bash
conan profile detect
```
2. **Install Conan dependencies:**
```bash
conan install . --output-folder=build --build=missing
```
3. **Configure the project with CMake:**
```bash
cmake --preset conan-release
```
*(Alternatively: `cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release`)*
4. **Build the project:**
```bash
cmake --build build -j10
```
### Make python package
```bash
micromamba run -n mutom env USE_CUDA=ON poetry install
```

36
build.log Normal file
View File

@@ -0,0 +1,36 @@
make: Entering directory '/home/rigoni/devel/cmt/ulib/build'
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/VoxImage.cpp.o
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/TriangleMesh.cpp.o
[ 30%] Building CXX object src/Core/CMakeFiles/mutomCore.dir/Options.cpp.o
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/Dense.cpp.o
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/StructuredGrid.cpp.o
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/VoxRaytracer.cpp.o
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/StructuredData.cpp.o
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/Structured2DGrid.cpp.o
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/Structured4DGrid.cpp.o
[ 33%] Linking CXX shared library libmutomCore.so
[ 33%] Built target mutomCore
[ 36%] Linking CXX shared library libmutomMath.so
[ 36%] Built target mutomMath
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/vtkContainerBox.cpp.o
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/uLibVtkInterface.cxx.o
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/vtkStructuredGrid.cpp.o
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/vtkMuonScatter.cxx.o
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/uLibVtkViewer.cpp.o
[ 63%] Generating mutomRootDict.cxx, libmutomRootDict_rdict.pcm, libmutomRootDict.rootmap
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/vtkVoxImage.cpp.o
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/vtkVoxRaytracerRepresentation.cpp.o
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/muCastorSkinHit.cpp.o
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/muCastorHit.cpp.o
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/muCastorMCTrack.cpp.o
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/muCastorInfo.cpp.o
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/RootMuonScatter.cpp.o
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/muCastorPrimaryVertex.cpp.o
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/muCastorMuDetDIGI.cpp.o
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/SkinDetectorWriter.cpp.o
[ 93%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/mutomRootDict.cxx.o
[ 96%] Linking CXX shared library libmutomVtk.so
[ 96%] Built target mutomVtk
[100%] Linking CXX shared library libmutomRoot.so
[100%] Built target mutomRoot
make: Leaving directory '/home/rigoni/devel/cmt/ulib/build'

54
build_python.py Normal file
View File

@@ -0,0 +1,54 @@
import os
import subprocess
import sys
import shutil
def build(setup_kwargs):
"""
Build the C++ extension using CMake.
This function is called by poetry-core during the build process.
The binary is placed directly inside the uLib directory in src/Python.
"""
# Root of the whole project where this build_extension.py is located
project_root = os.path.abspath(os.path.dirname(__file__))
# Where the extension should go
package_dir = os.path.join(project_root, "src/Python/uLib")
# Ensure package directory exists
os.makedirs(package_dir, exist_ok=True)
# Temporary build directory
build_temp = os.path.join(project_root, "build_python")
os.makedirs(build_temp, exist_ok=True)
print(f"--- Running CMake build in {build_temp} ---")
print(f"Project root: {project_root}")
print(f"Target binary dir: {package_dir}")
# Determine if CUDA should be enabled
use_cuda = os.environ.get("USE_CUDA", "OFF").upper()
if use_cuda in ["ON", "1", "TRUE", "YES"]:
use_cuda = "ON"
else:
use_cuda = "OFF"
# CMake configuration
cmake_args = [
f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={package_dir}",
f"-DPYTHON_EXECUTABLE={sys.executable}",
"-DCMAKE_BUILD_TYPE=Release",
f"-DUSE_CUDA={use_cuda}",
"-G", "Unix Makefiles",
]
# Use micromamba to ensure Boost and VTK are found during the build
subprocess.check_call(["cmake", project_root] + cmake_args, cwd=build_temp)
subprocess.check_call(["cmake", "--build", ".", "--parallel", "--target", "uLib_python"], cwd=build_temp)
# Ensure the package is found by poetry during the wheel creation process.
# Return setup_kwargs for poetry-core.
return setup_kwargs
if __name__ == "__main__":
build({})

8
conanfile.txt Normal file
View File

@@ -0,0 +1,8 @@
[requires]
eigen/3.4.0
boost/1.83.0
pybind11/3.0.2
[generators]
CMakeDeps
CMakeToolchain

10
condaenv.yml Normal file
View File

@@ -0,0 +1,10 @@
name: mutom
channels:
- conda-forge
dependencies:
- compiler-rt
- make
- cmake
- conan
- root
- vtk

View File

@@ -0,0 +1,41 @@
.tabbed-set {
display: flex;
position: relative;
flex-wrap: wrap;
}
.tabbed-set .highlight {
background: #ddd;
}
.tabbed-set .tabbed-content {
display: none;
order: 99;
width: 100%;
}
.tabbed-set label {
width: auto;
margin: 0 0.5em;
padding: 0.25em;
font-size: 120%;
cursor: pointer;
color: #ffffff !important;
}
.tabbed-set input {
position: absolute;
opacity: 0;
}
.tabbed-set input:nth-child(n+1) {
color: #333333;
}
.tabbed-set input:nth-child(n+1):checked + label {
color: cyan !important;
}
.tabbed-set input:nth-child(n+1):checked + label + .tabbed-content {
display: block;
}

17
docs/assets/css/extra.css Normal file
View File

@@ -0,0 +1,17 @@
@import "extensions/tabbed.css";
.md-grid {
max-width: 100%;
}
.md-main__inner {
margin-top: 0;
padding-top: 0;
}
.md-sidebar--secondary {
right: 1.5rem;
top: 4.8rem;
transform: none;
width: 18rem;
}

30
docs/docker/Dockerfile Normal file
View File

@@ -0,0 +1,30 @@
# Stage 1: Build the static site using MkDocs
FROM python:3.9-slim-buster as builder
# Set the working directory
WORKDIR /app
# Copy the requirements file
COPY requirements.txt .
# Install the Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Copy the rest of the application files
COPY ../.. .
# Build the MkDocs site
RUN mkdocs build
# Stage 2: Serve the static files with Nginx
FROM nginx:alpine
# Copy the built site from the builder stage
COPY --from=builder /app/site /usr/share/nginx/html
# Expose port 80 for the web server
EXPOSE 80
# Command to run Nginx in the foreground
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -0,0 +1,14 @@
# Dockerfile for development with live-reloading
FROM python:3.9-slim-buster
WORKDIR /app
# Copy and install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Expose the port MkDocs serve will run on
EXPOSE 8000
# Command to run the development server
CMD ["mkdocs", "serve", "--dev-addr", "0.0.0.0:8000"]

View File

@@ -0,0 +1,13 @@
version: '3.8'
services:
mkdocs:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "8000:8000"
volumes:
- ../..:/app
environment:
- GIT_DISCOVERY_ACROSS_FILESYSTEM=1

View File

@@ -0,0 +1,17 @@
# ------------------------------------------------------------------
# MkDocs runtime dependencies for the docs Docker image
# ------------------------------------------------------------------
# Core: theme (provides mkdocs itself as a transitive dep)
mkdocs-material==9.7.1
# pymdownx.* extensions used in mkdocs.yml:
# arithmatex, highlight, superfences, tabbed, details, blocks.caption
# (also a hard dep of mkdocs-material, pinned here for reproducibility)
pymdown-extensions>=10.0
# Markdown math rendering support (arithmatex generic mode)
# JS side is loaded via CDN (polyfill.io + MathJax), no extra Python pkg needed
# Optional: PDF export plugin (exporter: block, currently commented out in mkdocs.yml)
mkdocs-exporter

1
docs/docker/runtime.txt Normal file
View File

@@ -0,0 +1 @@
3.7

63
docs/index.md Normal file
View File

@@ -0,0 +1,63 @@
# uLib
[![DOI](https://zenodo.org/badge/36926725.svg)](https://zenodo.org/badge/latestdoi/36926725)
**uLib** is the base toolkit library for the **CMT (Cosmic Muon Tomography)** project, developed at the University of Padova and INFN Sezione di Padova, Italy.
It provides:
- **Core** object model, timers, configuration, UUID utilities.
- **Math** linear algebra (Eigen3), structured grids, voxel images, ray-tracing, image filters.
- **Python bindings** full pybind11 interface for scripting and analysis workflows.
- Optional **CUDA** acceleration for voxel filtering (transparent RAM ↔ VRAM management).
---
## Quick Start
=== "Users (pip / poetry)"
```bash
# Activate your conda/micromamba environment first
micromamba activate mutom
poetry install # CPU build
USE_CUDA=ON poetry install # GPU build
```
=== "Developers (CMake)"
```bash
conan install . --output-folder=build --build=missing
cmake --preset conan-release
cmake --build build --target uLib_python -j$(nproc)
export PYTHONPATH="$(pwd)/build/src/Python:$(pwd)/src/Python"
```
Then in Python:
```python
import uLib
# Core
timer = uLib.Core.Timer()
timer.Start()
# Math
grid = uLib.Math.StructuredGrid([10, 10, 10])
grid.SetSpacing([1.0, 1.0, 1.0])
img = uLib.Math.VoxImage([10, 10, 10])
img.SetValue(0, 3.14)
print(img.GetValue(0))
```
---
## Documentation Sections
| Section | Description |
|---|---|
| [Python Installation](python/installation.md) | Environment setup, user install, developer build |
| [Python API Usage](python/usage.md) | Full API reference with examples |
| [Python Developer Guide](python/developer_guide.md) | Adding bindings, running tests, build details |
| [C++ Build Usage & CUDA](usage/usage.md) | CMake build, CUDA configuration |

View File

@@ -0,0 +1,179 @@
# Developer Guide Python Bindings
This guide is aimed at contributors who want to extend or modify the Python bindings for `uLib`.
---
## Repository Layout
```
ulib/
├── src/
│ └── Python/
│ ├── module.cpp # pybind11 module entry point
│ ├── core_bindings.cpp # uLib::Core bindings
│ ├── math_bindings.cpp # uLib::Math bindings
│ ├── math_filters_bindings.cpp# VoxImageFilter bindings
│ ├── CMakeLists.txt # builds uLib_python shared lib
│ ├── testing/ # Python unit tests
│ │ ├── pybind_test.py
│ │ ├── core_pybind_test.py
│ │ ├── math_pybind_test.py
│ │ └── math_filters_test.py
│ └── uLib/ # Python package (uLib_python.so lands here)
│ └── __init__.py
├── build_python.py # poetry build hook (calls CMake)
├── pyproject.toml # poetry metadata
└── condaenv.yml # conda/micromamba environment
```
---
## Adding a New Binding
All bindings live in the four source files listed above. The module entry point `module.cpp` calls `init_core()`, `init_math()`, and `init_math_filters()` in order.
### 1. Pick (or create) the right binding file
| C++ header location | Binding file |
|---|---|
| `src/Core/` | `core_bindings.cpp` |
| `src/Math/` (geometry, grids, VoxImage) | `math_bindings.cpp` |
| `src/Math/VoxImageFilter*.hpp` | `math_filters_bindings.cpp` |
### 2. Add the `#include` directive
```cpp
// math_bindings.cpp
#include "Math/MyNewClass.h"
```
### 3. Write the pybind11 binding inside the appropriate `init_*` function
```cpp
void init_math(py::module_ &m) {
// ... existing bindings ...
py::class_<MyNewClass>(m, "MyNewClass")
.def(py::init<>())
.def("MyMethod", &MyNewClass::MyMethod)
.def("AnotherMethod", &MyNewClass::AnotherMethod,
py::arg("x"), py::arg("y") = 0.0f);
}
```
### 4. Rebuild only the Python target
```bash
cmake --build build --target uLib_python -j$(nproc)
```
### 5. Write a Python test
Add a new test class to the relevant test file (or create a new one under `src/Python/testing/`):
```python
# src/Python/testing/math_pybind_test.py
class TestMyNewClass(unittest.TestCase):
def test_basic(self):
obj = uLib.Math.MyNewClass()
result = obj.MyMethod()
self.assertAlmostEqual(result, expected_value)
```
Register the test in `src/Python/CMakeLists.txt` if you add a new file:
```cmake
add_test(NAME pybind_my_new
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/my_new_test.py)
set_tests_properties(pybind_my_new PROPERTIES
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:uLib_python>:${PROJECT_SOURCE_DIR}/src/Python")
```
---
## Build System Details
### CMakeLists.txt (`src/Python/`)
`pybind11_add_module` compiles the shared library `uLib_python` and links it against the C++ static/shared libraries `uLibCore` and `uLibMath`. The install target copies the `.so` into the standard library directory.
```cmake
pybind11_add_module(uLib_python
module.cpp core_bindings.cpp math_bindings.cpp math_filters_bindings.cpp)
target_link_libraries(uLib_python PRIVATE uLibCore uLibMath)
```
### poetry / build_python.py
`pyproject.toml` declares `build_python.py` as the custom build hook. When `poetry install` or `poetry build` is invoked it:
1. Calls `cmake <root> -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=<pkg_dir> ...` in `build_python/`.
2. Builds only the `uLib_python` target.
3. The resulting `.so` is placed inside `src/Python/uLib/` so it is picked up by Poetry as a package data file.
The `USE_CUDA` environment variable gates CUDA support at build time:
```bash
USE_CUDA=ON poetry install # with CUDA
USE_CUDA=OFF poetry install # CPU only (default)
```
---
## Running All Tests
```bash
# From the repository root, with PYTHONPATH set:
export PYTHONPATH="$(pwd)/build/src/Python:$(pwd)/src/Python"
python -m pytest src/Python/testing/ -v
```
Or through CMake's test runner (after building the full project):
```bash
cd build
ctest --output-on-failure -R pybind
```
Expected output (all passing):
```
Start 1: pybind_general
1/4 Test #1: pybind_general ............. Passed
Start 2: pybind_core
2/4 Test #2: pybind_core ................ Passed
Start 3: pybind_math
3/4 Test #3: pybind_math ................ Passed
Start 4: pybind_math_filters
4/4 Test #4: pybind_math_filters ........ Passed
```
---
## Memory Management Notes
`uLib::Vector<T>` has explicit GPU memory management. When wrapping methods that return references to internal data, use `py::return_value_policy::reference_internal` to avoid dangling references:
```cpp
.def("Data", &VoxImage<Voxel>::Data,
py::return_value_policy::reference_internal)
```
For objects held by `std::unique_ptr` without Python-side deletion, use `py::nodelete`:
```cpp
py::class_<Abstract::VoxImageFilter,
std::unique_ptr<Abstract::VoxImageFilter, py::nodelete>>(m, "AbstractVoxImageFilter")
```
---
## Useful References
- [pybind11 documentation](https://pybind11.readthedocs.io)
- [pybind11 STL containers](https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html)
- [pybind11 Eigen integration](https://pybind11.readthedocs.io/en/stable/advanced/cast/eigen.html)
- [CMake pybind11 integration](https://pybind11.readthedocs.io/en/stable/compiling.html)

146
docs/python/installation.md Normal file
View File

@@ -0,0 +1,146 @@
# Python Installation
The `uLib` Python package exposes the Core and Math C++ libraries via [pybind11](https://pybind11.readthedocs.io) bindings. There are two ways to install it: as an **end user** (pre-built wheel / pip) or as a **developer** (editable build from source).
---
## Prerequisites
`uLib` depends on native C++ libraries that must be compiled. Ensure the following are available in your environment before installing:
| Dependency | Minimum version | Notes |
|---|---|---|
| Python | 3.9 | |
| CMake | 3.12 | |
| pybind11 | 2.6.0 | |
| Conan | 2.x | for Eigen3 / Boost |
| micromamba / conda | any | recommended provides ROOT, VTK |
### Creating the `mutom` Conda/Micromamba Environment
A ready-to-use environment definition is provided as `condaenv.yml` at the repository root.
=== "Micromamba"
```bash
micromamba env create -f condaenv.yml
micromamba activate mutom
```
=== "Conda"
```bash
conda env create -f condaenv.yml
conda activate mutom
```
The environment installs CMake, Conan, ROOT, VTK, and the compiler toolchain.
> **CUDA (optional)**
> If you want GPU-accelerated voxel filtering, you also need NVCC inside the environment:
> ```bash
> micromamba install cuda-nvcc -c conda-forge
> ```
---
## User Installation (wheel / pip)
Once the native dependencies are present in your environment, install the package with Poetry or pip:
```bash
# Activate your environment first
micromamba activate mutom
# Build and install (CUDA disabled by default)
poetry install
# Build and install with CUDA support
USE_CUDA=ON poetry install
```
After installation the module is importable from anywhere in the environment:
```python
import uLib
print(dir(uLib.Core))
print(dir(uLib.Math))
```
---
## Developer Installation (editable / in-tree build)
For development you typically want to skip the packaging layer and work directly against the CMake build tree.
### Step 1 Install Conan dependencies
```bash
conan profile detect # first time only
conan install . --output-folder=build --build=missing
```
### Step 2 Configure and build
```bash
# Standard release build
cmake --preset conan-release
# …or manually
cmake -B build \
-DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DUSE_CUDA=OFF # set to ON when a GPU is available
cmake --build build --target uLib_python -j$(nproc)
```
The shared library (`uLib_python*.so`) is written to `build/src/Python/`.
### Step 3 Make the module importable
Point `PYTHONPATH` at the build output **and** the Python source directory (the latter carries the `uLib/__init__.py` that stitches sub-modules together):
```bash
export PYTHONPATH="$(pwd)/build/src/Python:$(pwd)/src/Python:$PYTHONPATH"
python -c "import uLib; print(uLib.__version__)"
```
Or, for a one-shot check:
```bash
PYTHONPATH="build/src/Python:src/Python" python src/Python/testing/pybind_test.py
```
### Step 4 Run the tests
CMake registers the Python tests alongside the C++ ones; use `ctest` from the build directory:
```bash
cd build
ctest --output-on-failure -R pybind
```
Individual test scripts can also be run directly once `PYTHONPATH` is set:
```bash
python src/Python/testing/core_pybind_test.py
python src/Python/testing/math_pybind_test.py
python src/Python/testing/math_filters_test.py
```
---
## Verifying the Installation
```python
import uLib
# Core module
obj = uLib.Core.Object()
timer = uLib.Core.Timer()
timer.Start()
elapsed = timer.StopWatch() # float, seconds
# Math module
v3 = uLib.Math.Vector3f([1.0, 0.0, 0.0])
print(v3[0]) # 1.0
```

373
docs/python/usage.md Normal file
View File

@@ -0,0 +1,373 @@
# Python API Usage
The `uLib` Python package is split into two sub-modules mirroring the C++ library:
| Sub-module | Contents |
|---|---|
| `uLib.Core` | Low-level utilities: `Object`, `Timer`, `Options`, `TypeRegister` |
| `uLib.Math` | Geometry, grids, voxel images, ray-tracing, image filters |
```python
import uLib
# Sub-modules are accessible as attributes
uLib.Core # core utilities
uLib.Math # mathematical structures
```
---
## uLib.Core
### Object
Base class for uLib objects; exposed to Python for type-hierarchy purposes.
```python
obj = uLib.Core.Object()
copy = obj.DeepCopy()
```
### Timer
Precision wall-clock timer.
```python
import time
timer = uLib.Core.Timer()
timer.Start()
time.sleep(0.5)
elapsed = timer.StopWatch() # returns elapsed seconds as float
print(f"Elapsed: {elapsed:.3f} s")
```
### Options
Wraps Boost.ProgramOptions for INI-style configuration files.
```python
opt = uLib.Core.Options("My Program")
opt.parse_config_file("config.ini") # load settings
n = opt.count("my_key") # check if key exists
opt.save_config_file("out.ini")
```
---
## uLib.Math Linear Algebra
The math module exposes Eigen3 vectors and matrices as well-typed Python objects with NumPy interoperability.
### Fixed-size Vectors
```python
import numpy as np
import uLib
# Construct from list
v3 = uLib.Math.Vector3f([1.0, 2.0, 3.0])
print(v3[0], v3[1], v3[2]) # 1.0 2.0 3.0
# Construct from NumPy array
arr = np.array([4.0, 5.0, 6.0], dtype=np.float32)
v3b = uLib.Math.Vector3f(arr)
# Zero-initialise
v4d = uLib.Math.Vector4d() # all zeros
# Available types
# Vector1f / 2f / 3f / 4f (float32)
# Vector1d / 2d / 3d / 4d (float64)
# Vector1i / 2i / 3i / 4i (int32)
```
### Fixed-size Matrices
```python
# 2-by-2 float matrix
m2f = uLib.Math.Matrix2f()
m2f[0, 0] = 1; m2f[0, 1] = 2
m2f[1, 0] = 3; m2f[1, 1] = 4
# From list (row-major)
m4f = uLib.Math.Matrix4f([1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1])
# From NumPy (2-D array)
mat = np.eye(3, dtype=np.float32)
m3f = uLib.Math.Matrix3f(mat)
# Dynamic matrices
mXf = uLib.Math.MatrixXf(4, 4) # 4×4 float, zeros
```
### Homogeneous Types
```python
# HPoint3f a 3-D point in homogeneous coordinates (w = 1)
p = uLib.Math.HPoint3f(1.0, 2.0, 3.0)
# HVector3f a free vector (w = 0)
v = uLib.Math.HVector3f(0.0, 1.0, 0.0)
# HLine3f a parametric ray
line = uLib.Math.HLine3f()
line.origin = uLib.Math.HPoint3f(0, 0, 0)
line.direction = uLib.Math.HVector3f(0, 0, 1)
```
---
## uLib.Math Transforms and Geometry
### AffineTransform
A rigid-body / affine transform stored as a 4×4 matrix.
```python
tf = uLib.Math.AffineTransform()
tf.SetPosition([1.0, 0.0, 0.0]) # translate
tf.Translate([0.0, 1.0, 0.0]) # cumulative translate
tf.Scale([2.0, 2.0, 2.0]) # uniform scale
tf.Rotate(uLib.Math.Vector3f([0, 0, 3.14159])) # Euler angles (rad)
mat4 = tf.GetWorldMatrix() # 4×4 matrix
pos = tf.GetPosition() # Vector3f
```
### Geometry
Inherits `AffineTransform`; converts points between world and local frames.
```python
geo = uLib.Math.Geometry()
geo.SetPosition([1.0, 1.0, 1.0])
world_pt = uLib.Math.Vector4f([2.0, 3.0, 2.0, 1.0])
local_pt = geo.GetLocalPoint(world_pt)
back = geo.GetWorldPoint(local_pt)
# back ≈ [2, 3, 2, 1]
```
### ContainerBox
An axis-aligned bounding box with an associated transform.
```python
box = uLib.Math.ContainerBox()
box.SetOrigin([-1.0, -1.0, -1.0])
box.SetSize([2.0, 2.0, 2.0])
print(box.GetSize()) # [2, 2, 2]
```
---
## uLib.Math Structured Grids
### StructuredGrid (3-D)
A 3-D voxel grid (origin, spacing, and integer dimensions).
```python
dims = uLib.Math.Vector3i([10, 10, 10])
grid = uLib.Math.StructuredGrid(dims)
grid.SetSpacing([1.0, 1.0, 1.0])
grid.SetOrigin([0.0, 0.0, 0.0])
print(grid.GetSpacing()) # [1, 1, 1]
print(grid.IsInsideBounds([5, 5, 5, 1])) # True
idx = grid.Find([2.5, 2.5, 2.5]) # returns grid cell index
```
### Structured2DGrid / Structured4DGrid
```python
grid2d = uLib.Math.Structured2DGrid()
grid2d.SetDims([100, 100])
grid2d.SetPhysicalSpace([0, 0], [1, 1])
print(grid2d.GetSpacing())
```
---
## uLib.Math VoxImage
`VoxImage` is a 3-D voxel volume where each cell stores a `Voxel` ( `.Value` + `.Count`).
```python
dims = uLib.Math.Vector3i([20, 20, 20])
img = uLib.Math.VoxImage(dims)
img.SetSpacing([0.5, 0.5, 0.5])
# Access by linear index
img.SetValue(0, 42.0)
print(img.GetValue(0)) # 42.0
# Access by 3-D index
img.SetValue(uLib.Math.Vector3i([1, 1, 1]), 7.5)
print(img.GetValue(uLib.Math.Vector3i([1, 1, 1]))) # 7.5
# Clipping / masking helpers
cropped = img.clipImage(uLib.Math.Vector3i([2, 2, 2]),
uLib.Math.Vector3i([18, 18, 18]))
masked = img.maskImage(0.0, 100.0, 0.0) # mask outside [0, 100]
# I/O
img.ExportToVti("output.vti")
img.ImportFromVti("output.vti")
```
### Voxel (element type)
```python
vox = uLib.Math.Voxel()
vox.Value = 1.5
vox.Count = 3
data = img.Data() # returns the underlying Vector_Voxel
vox0 = data[0]
print(vox0.Value, vox0.Count)
```
---
## uLib.Math VoxRaytracer
Performs ray-tracing through a `StructuredGrid` and returns per-voxel chord lengths.
```python
import numpy as np
import uLib
grid = uLib.Math.StructuredGrid([10, 10, 10])
grid.SetSpacing([1.0, 1.0, 1.0])
grid.SetOrigin([0.0, 0.0, 0.0])
rt = uLib.Math.VoxRaytracer(grid)
# Trace a ray between two homogeneous points (x, y, z, w=1)
p1 = np.array([0.5, 0.5, -1.0, 1.0], dtype=np.float32)
p2 = np.array([0.5, 0.5, 11.0, 1.0], dtype=np.float32)
result = rt.TraceBetweenPoints(p1, p2)
print("Voxels crossed:", result.Count())
print("Total length :", result.TotalLength())
elements = result.Data()
for i in range(result.Count()):
print(f" vox_id={elements[i].vox_id} L={elements[i].L:.4f}")
```
---
## uLib.Math Image Filters
All filters share the same interface: construct with a kernel size, attach a `VoxImage`, optionally set parameters, then call `.Run()`.
```python
import uLib
dims = uLib.Math.Vector3i([10, 10, 10])
img = uLib.Math.VoxImage(dims)
for i in range(10**3):
img.SetValue(i, float(i))
kernel_dims = uLib.Math.Vector3i([3, 3, 3])
```
### Linear (Gaussian / Box) Filter
```python
filt = uLib.Math.VoxFilterAlgorithmLinear(kernel_dims)
filt.SetImage(img)
filt.SetKernelNumericXZY([1.0] * 27) # uniform box kernel, length = product of dims
filt.Run()
```
### ABTrim Filter
Applies alpha-beta trimming to remove outliers before averaging.
```python
filt = uLib.Math.VoxFilterAlgorithmAbtrim(kernel_dims)
filt.SetImage(img)
filt.SetKernelNumericXZY([1.0] * 27)
filt.SetABTrim(2, 2) # trim 2 low and 2 high values
filt.Run()
```
### Bilateral Filter
Edge-preserving smoothing controlled by a spatial sigma (from the kernel shape) and an intensity sigma.
```python
filt = uLib.Math.VoxFilterAlgorithmBilateral(kernel_dims)
filt.SetImage(img)
filt.SetKernelNumericXZY([1.0] * 27)
filt.SetIntensitySigma(0.3)
filt.Run()
```
### Threshold Filter
Zeros voxels below a threshold.
```python
filt = uLib.Math.VoxFilterAlgorithmThreshold(kernel_dims)
filt.SetImage(img)
filt.SetKernelNumericXZY([1.0] * 27)
filt.SetThreshold(0.5)
filt.Run()
```
### Median Filter
```python
filt = uLib.Math.VoxFilterAlgorithmMedian(kernel_dims)
filt.SetImage(img)
filt.SetKernelNumericXZY([1.0] * 27)
filt.Run()
```
---
## uLib.Math Accumulators
Accumulators collect scalar samples and return a summary statistic.
```python
# Arithmetic mean
acc = uLib.Math.Accumulator_Mean_f()
acc(10.0)
acc(20.0)
mean = acc() # 15.0
# Alpha-beta trimmed mean
acc2 = uLib.Math.Accumulator_ABTrim_f()
acc2.SetABTrim(0.1, 0.1) # trim bottom 10 % and top 10 %
acc2 += 1.0
acc2 += 9999.0 # outlier
acc2 += 5.0
result = acc2() # trimmed mean ≈ 3.0
```
---
## Dynamic Vectors (`uLib.Math.Vector_*`)
Typed dynamic arrays backed by `uLib::Vector<T>` with optional CUDA memory management.
```python
# Integer vector
vi = uLib.Math.Vector_i()
vi.append(1); vi.append(2); vi.append(3)
print(len(vi), vi[0])
# Float vector with CUDA management
vf = uLib.Math.Vector_f()
vf.append(1.5)
vf.MoveToVRAM() # copy to GPU (no-op when CUDA is absent)
vf.MoveToRAM() # copy back to CPU
# Other types: Vector_ui, Vector_l, Vector_ul, Vector_d
# Compound element types: Vector_Vector3f, Vector_Vector4f, Vector_Voxel …
```

60
docs/usage/usage.md Normal file
View File

@@ -0,0 +1,60 @@
# Usage and Installation Guide
## Requirements
### Compiling with CUDA Support
The library supports running VoxImage filtering operations directly on CUDA cores via transparent RAM/VRAM memory transfers.
By default, the `CMakeLists.txt` build system sets `USE_CUDA=ON` and will attempt to locate `nvcc` and the NVIDIA CUDA Toolkit. If the toolkit is missing, `CMake` will fail unless you explicitly configure the project with `-DUSE_CUDA=OFF`.
### 1. Installing CUDA Environment via Micromamba
If you are developing inside an isolated Conda/Micromamba environment (e.g., `mutom`), you can inject the CUDA compilers directly into your environment rather than relying on global system dependencies:
```bash
# Add the conda-forge channel if not already available
micromamba config append channels conda-forge
# Install nvcc and the necessary CUDA toolkit components
micromamba install cuda-nvcc
```
Verify your installation:
```bash
nvcc --version
```
### 2. Building the Project
Configure and compile the project using standard CMake flows:
```bash
mkdir -p build && cd build
# Configure CMake
# (Optional) Explicitly toggle CUDA: cmake -DUSE_CUDA=ON ..
cmake ..
# Compile the project and tests
make -j $(nproc)
```
### 3. Validating CUDA Support
You can verify that the CUDA kernels are launching correctly and allocating device memory through `DataAllocator` by running the mathematical unit tests.
```bash
# From the build directory
./src/Math/testing/VoxImageFilterTest
# Output should show:
# "Data correctly stayed in VRAM after CUDA execution!"
```
## How It Works Under The Hood
The `DataAllocator<T>` container automatically wraps memory allocations to transparently map to CPU RAM, or GPU VRAM. Standard iteration automatically pulls data backwards using implicit `MoveToRAM()` calls.
Filters using `#ifdef USE_CUDA` explicitly dictate `<buffer>.MoveToVRAM()` allocating directly on device bounds seamlessly. Fallbacks to Host compute iterations handle themselves automatically. Chaining specific filters together safely chains continuous VRAM operations avoiding costly Host copies in between iterations.

561
mkdocs.yml Normal file
View File

@@ -0,0 +1,561 @@
# site_name: uLib Documentation
# site_description: CMT Cosmic Muon Tomography uLib toolkit
# site_author: Andrea Rigoni Garola
# repo_url: https://github.com/cmt/ulib
# docs_dir: docs
# +--------------------------------------------------------------------------------------------------------+
# | |
# | This is the main file used by MkDocs to build the pages. |
# | It contains a lot of information and settings for you to read and use. |
# | Comments may contain "Read More" URLs to more in-depth documentation about the option for you to read. |
# | |
# | You can check out https://www.mkdocs.org/user-guide/configuration/ for a more detailed explanation of |
# | all the options MkDocs offers by default. |
# | |
# +------------------------------------------------- NOTE -------------------------------------------------+
# | |
# | Some of the options listed here are only available through the usage of Material for MkDocs. |
# | Those options will usually have a link to the docs of this Theme and also mention "Material" as name. |
# | The actual name of the theme is "Material for MkDocs" and "Material" is used for simplicity reasons. |
# | |
# +--------------------------------------------------------------------------------------------------------+
# +--------------------------------------------------------------------------------------------------------+
# | |
# | Main Page Settings for MkDocs. |
# | Those settings are site name, site description, Site author and also Site URL (Canonical URL) |
# | |
# | Read More: |
# | - https://www.mkdocs.org/user-guide/configuration/#site_name |
# | - https://www.mkdocs.org/user-guide/configuration/#site_description |
# | - https://www.mkdocs.org/user-guide/configuration/#site_author |
# | - https://www.mkdocs.org/user-guide/configuration/#site_url |
# | |
# +--------------------------------------------------------------------------------------------------------+
site_name: OpenCMT uLib Documentation
site_url: https://docs.mildstone.org/uLib/ # <--- project subfolder
use_directory_urls: true
site_description: 'Documentation for OpenCMT uLib'
site_author: 'Andrea Rigoni Garola'
# +--------------------------------------------------------------------------------------------------------+
# | |
# | This setting allows you to define your own Copyright notice. |
# | The text is treated as HTML code so you can use things like <a> tags or &copy; to display the |
# | Copyright icon. |
# | |
# | Where or IF the Copyright is displayed depends on the theme you use. |
# | |
# | Read More: |
# | - https://www.mkdocs.org/user-guide/configuration/#copyright |
# | |
# +--------------------------------------------------------------------------------------------------------+
copyright: |
&copy; Author
# +--------------------------------------------------------------------------------------------------------+
# | |
# | The base folder to use. |
# | Any Markdown files you put into this folder will be turned into a static HTML page once you build or |
# | publish your page. |
# | |
# | It is also used as the base directory for other settings like the "extra_css" or "extra_javascript" |
# | option. |
# | |
# +--------------------------------------------------------------------------------------------------------+
docs_dir: docs/
# +--------------------------------------------------------------------------------------------------------+
# | |
# | These options allow to define a Repository to link to. |
# | The result will, depending on the theme, be a link somewhere shown on the page that links to the |
# | Repository with the specified repo_name. |
# | |
# | This will also enable a "edit" button on the page itself that allows the direct editing of the page. |
# | You can disable this by setting "edit_uri" to an empty String. |
# | |
# | Read More: |
# | - https://www.mkdocs.org/user-guide/configuration/#repo_name |
# | - https://www.mkdocs.org/user-guide/configuration/#repo_url |
# | - https://www.mkdocs.org/user-guide/configuration/#edit_uri |
# | |
# +--------------------------------------------------------------------------------------------------------+
repo_name: OpenCMT/uLib
repo_url: https://gitea.mildstone.org/OpenCMT/uLib.git
#edit_uri: tree/master/docs # Uncomment to define a different URI/URL for the "edit" option
# +--------------------------------------------------------------------------------------------------------+
# | |
# | The "nav" option is where you define the navigation to show in MkDocs. |
# | |
# | Depending on the theme you use will the resulting Navigation look different. |
# | |
# | You can set different types of navigations. Either just the path, the path with a separate title or |
# | an external URL. |
# | |
# | Read More: |
# | - https://www.mkdocs.org/user-guide/configuration/#documentation-layout |
# | |
# +--------------------------------------------------------------------------------------------------------+
nav:
- Home: index.md
- Python:
- Installation: python/installation.md
- API Usage: python/usage.md
- Developer Guide: python/developer_guide.md
- C++ Build:
- Usage & CUDA: usage/usage.md
# +--------------------------------------------------------------------------------------------------------+
# | |
# | The "theme" section allows you to define what theme to use. |
# | It is also used for theme-specific options, but also for advanced stuff such as theme-extensions, if |
# | the theme actually supports it. |
# | |
# | Read More: |
# | - https://www.mkdocs.org/user-guide/configuration/#theme |
# | |
# +--------------------------------------------------------------------------------------------------------+
theme:
# +------------------------------------------------------------------------------------------------------+
# | |
# | The "name" option is where you define the theme to use. |
# | |
# | Note that not all themes are included by default and will require you to install them first. |
# | The Material theme is one of them. See the "Read More" link for instructions on how to install it. |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/getting-started/ |
# | |
# +------------------------------------------------------------------------------------------------------+
name: 'material'
# +------------------------------------------------------------------------------------------------------+
# | |
# | The Material theme allows "theme-extsnions", meaning that you can override parts of it by either |
# | overriding a particular file, or only parts (blocks) of it. |
# | |
# | If you want to override parts of Material, uncomment the "custom_dir" option below and set the |
# | folder (relative to the mkdocs.yml file) where your theme extensions will be located at. |
# | |
# | Read More: |
# | - https://www.mkdocs.org/user-guide/configuration/#custom_dir |
# | - https://squidfunk.github.io/mkdocs-material/customization/#extending-the-theme |
# | |
# +------------------------------------------------------------------------------------------------------+
#custom_dir: 'theme'
# +------------------------------------------------------------------------------------------------------+
# | |
# | The "favicon" option allows you to set your own image/icon to use in the browser-tab. |
# | |
# | Pretty much all image types are supported, but it's recommended to use a PNG, SVG or ICO image for |
# | the favicon. |
# | |
# | The directory is relative to the "docs_dir". |
# | |
# | Example: Having a favicon.png in docs/assets/images will result in the "favicon" setting showing |
# | 'assets/images/favicon.png' |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/setup/changing-the-logo-and-icons/#favicon |
# | |
# +------------------------------------------------------------------------------------------------------+
#favicon: 'assets/images/favicon.png'
# +------------------------------------------------------------------------------------------------------+
# | |
# | The "palette" section is a Material option and allows you to define specific style options such as |
# | Color-Scheme, and primary and secondary Color. |
# | |
# | You can also define multiple palettes that can have different Color Schemses and primary and/or |
# | secondary Colors. |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/ |
# | - https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/#color-palette-toggle |
# | |
# +------------------------------------------------------------------------------------------------------+
palette:
# Palette toggle for light mode
- media: "(prefers-color-scheme: light)"
scheme: default
primary: 'indigo'
accent: 'indigo'
toggle:
icon: material/brightness-7
name: Switch to dark mode
# Palette toggle for dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: 'indigo'
accent: 'indigo'
toggle:
icon: material/brightness-4
name: Switch to light mode
# +------------------------------------------------------------------------------------------------------+
# | |
# | With the "font" option can you set a different font to use. |
# | |
# | Material supports all Google fonts, but you can also define your own ones if you choose so. |
# | |
# | The "text" option is used for the regular font while "code" is used for code blocks, inline code and |
# | similar. |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/setup/changing-the-fonts/ |
# | |
# +------------------------------------------------------------------------------------------------------+
#font:
# text: 'Roboto'
# code: 'Roboto Mono'
# +------------------------------------------------------------------------------------------------------+
# | |
# | Material suppors more than 40 different languages which you can set using the "language" option |
# | below. |
# | |
# | The default language is "en" (English). |
# | |
# | You can also enable/set a "selector" to allow switching between languages. |
# | See the "alternate" option in the "extra" section below for more information on this topic. |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/setup/changing-the-language/ |
# | |
# +------------------------------------------------------------------------------------------------------+
#language: 'en'
# +------------------------------------------------------------------------------------------------------+
# | |
# | The "direction" option is commonly used together with the "language" option. |
# | |
# | It allows you to change the text direction from the default left-to-right (ltr) to right-to-left |
# | (rtl) which is used in certain languages. |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/setup/changing-the-language/#directionality |
# | |
# +------------------------------------------------------------------------------------------------------+
#direction: 'ltr'
# +------------------------------------------------------------------------------------------------------+
# | |
# | The "features" option allows you to enable specific features of Material, by adding them to the |
# | list. |
# | |
# | Features are in the format <category>.<name>. As an example, the feature to enable tabs is called |
# | navigation.tabs. |
# | |
# | The list below contains all known features of Material. |
# | |
# | Features marked with a * are currently Insiders-only. (Last update: 11th December 2021) |
# | https://squidfunk.github.io/mkdocs-material/insiders/ |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/setup/setting-up-navigation/ |
# | |
# +------------------------------------------------------------------------------------------------------+
features:
# Announce
#
#- announce.dismiss # Adds a "X" button to dismiss a news banner/mark it as read.*
# Header
#
#- header.autohide # Hide header when user scrolls past a specific point.
# Navigation:
#
#- navigation.expand # Expand all collapsable sections.
#- navigation.instant # Instant loading pages.
#- navigation.indexes # Attach pages directly to Sections. Incompatible with "toc.integrate"
#- navigation.sections # Render top sections as groups.
- navigation.tabs # Render top sections as tabs at the top.
#- navigation.tabs.sticky # Tabs won't disappear when scrolling down. Requires "navigation.tabs".
#- navigation.top # Adds a "Back to top" that is shown when scrolling up.
#- navigation.tracking # Updates the url with highlighted section anchor.
# Search
#
#- search.highlight # Search will highlight the searched word(s) on the page.*
#- search.share # Adds an option to share a search query link.*
#- search.suggest # Search will suggest the likeliest completion for a word.*
# Table of Contents
#
#- toc.integrate # Include the TOC sections in the left navugation.
# +------------------------------------------------------------------------------------------------------+
# | |
# | The "icon" section allows you to define a icon to use for the logo and/or repository. |
# | |
# | To use already available icons will you need to set the right path for it, depending on which you |
# | want to use. |
# | |
# | Available icons: |
# | - FontAwesome |
# | - Brands: fontawesome/brands/... (https://fontawesome.com/icons?d=gallery&p=2&s=brands&m=free) |
# | - Regular: fontawesome/regular/... (https://fontawesome.com/icons?d=gallery&p=2&s=regular&m=free) |
# | - Solid: fontawesome/solid/... (https://fontawesome.com/icons?d=gallery&p=2&s=solid&m=free) |
# | |
# | - Material Design Icons: material/... (https://materialdesignicons.com/) |
# | |
# | - Octicons: octicons/... (https://primer.style/octicons/) |
# | |
# | You can also define your own Image for the logo. To do that, remove the "logo" option from "icon" |
# | instead add a "logo" option on the same level as the "icon" one, where you then set the path |
# | (relative to the "docs_dir") to the icon to use. Supported are all images types, including SVG. |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/setup/changing-the-logo-and-icons/#logo |
# | |
# +------------------------------------------------------------------------------------------------------+
icon:
logo: 'material/library'
repo: 'material/library'
# +------------------------------------------------------------------------------------------------------+
# | |
# | The "admonition" option allows you to set a different icon for each admonition type. |
# | |
# | This is currently a Insiders-only feature. (Last update: 7th October 2021) |
# | https://squidfunk.github.io/mkdocs-material/insiders/ |
# | |
# | Supported are all bundled icons: |
# | - FontAwesome |
# | - Brands: fontawesome/brands/... (https://fontawesome.com/icons?d=gallery&p=2&s=brands&m=free) |
# | - Regular: fontawesome/regular/... (https://fontawesome.com/icons?d=gallery&p=2&s=regular&m=free) |
# | - Solid: fontawesome/solid/... (https://fontawesome.com/icons?d=gallery&p=2&s=solid&m=free) |
# | |
# | - Material Design Icons: material/... (https://materialdesignicons.com/) |
# | |
# | - Octicons: octicons/... (https://primer.style/octicons/) |
# | |
# | You can also create and use your own icons. See the documentation for more information. |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/reference/admonitions/#changing-the-icons |
# | |
# +------------------------------------------------------------------------------------------------------+
#admonition:
# note: 'octicons/tag-16'
# abstract: 'octicons/checklist-16'
# info: 'octicons/info-16'
# tip: 'octicons/squirrel-16'
# success: 'octicons/check-16'
# question: 'octicons/question-16'
# warning: 'octicons/alert-16'
# failure: 'octicons/x-circle-16'
# danger: 'octicons/zap-16'
# bug: 'octicons/bug-16'
# example: 'octicons/beaker-16'
# quote: 'octicons/quote-16'
# +--------------------------------------------------------------------------------------------------------+
# | |
# | With the "extra_css" option can you add your own (S)CSS files to enhance the documentation. |
# | |
# | The path to the file is relative to the "docs_dir". |
# | |
# | Read More: |
# | - https://www.mkdocs.org/user-guide/configuration/#extra_css |
# | |
# +--------------------------------------------------------------------------------------------------------+
extra_css:
- assets/css/extra.css
# +--------------------------------------------------------------------------------------------------------+
# | |
# | Similar to the "extra_css" option does the "extra_javascript" option allow you to set custom JS files |
# | to add extra featurues. |
# | |
# | The path to the file is relative to the "docs_dir". |
# | |
# | Read More: |
# | - https://www.mkdocs.org/user-guide/configuration/#extra_javascript |
# | |
# +--------------------------------------------------------------------------------------------------------+
extra_javascript:
- https://polyfill.io/v3/polyfill.min.js?features=es6
- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
# +--------------------------------------------------------------------------------------------------------+
# | |
# | The "extra" section contains pretty much anything you want, as long as it is a valid key-value pair. |
# | |
# | Material uses this section for different custom settings that wouldn't fit in the theme section. |
# | |
# | Read More: |
# | - https://www.mkdocs.org/user-guide/configuration/#extra |
# | |
# +--------------------------------------------------------------------------------------------------------+
extra:
# +------------------------------------------------------------------------------------------------------+
# | |
# | The social section allows you to set a list of entries which would be displayed in the footer of the |
# | page. |
# | |
# | Each entry has the exact same options: |
# | - icon: Path to the SVG icon to use. See "icon" section for available icon sets. |
# | - link: URL to which the icon should link. |
# | - name: Optional Name that would be displayed as title on hover. |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/setup/setting-up-the-footer/#social-links |
# | |
# +------------------------------------------------------------------------------------------------------+
social:
- icon: 'fontawesome/brands/github'
link: 'https://github.com/Andre601/mkdocs-template'
# +------------------------------------------------------------------------------------------------------+
# | |
# | Allows you to hide the "Made with Material for MkDocs" text in the footer of the pages by setting |
# | this to "true". |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/setup/setting-up-the-footer/#generator-notice |
# | |
# +------------------------------------------------------------------------------------------------------+
#generator: true
# +------------------------------------------------------------------------------------------------------+
# | |
# | The "manifest" option allows you to define a .manifest file to use. |
# | |
# | A .manifest file makes the doc act like a web-application and tells it how to behave when installed. |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/reference/meta-tags/#adding-a-web-app-manifest |
# | |
# +------------------------------------------------------------------------------------------------------+
#manifest: manifest.webmanifest
# +------------------------------------------------------------------------------------------------------+
# | |
# | The "alternate" option can be used to create a selector to switch languages. |
# | |
# | Using this requires you to create a specific, more complicated MkDocs setup. |
# | |
# | A Setup Guide for multi-language docs can be found here: |
# | https://github.com/squidfunk/mkdocs-material/discussions/2346 |
# | |
# | Read More: |
# | - https://squidfunk.github.io/mkdocs-material/setup/changing-the-language/#site-language-selector |
# | |
# +------------------------------------------------------------------------------------------------------+
#alternate:
# +--------------------------------------------------------------------------------------------------------+
# | |
# | MkDocs allows the usage of Markdown extensions which can do various things. |
# | |
# | Material includes the pymdownx extension which provides a lot of useful features to use. |
# | |
# | Note that some extensions may use specific settings that you need to set. |
# | Please check out the official documentation of PyMdownx for more information: |
# | https://facelessuser.github.io/pymdown-extensions/ |
# | |
# | Material already provides required CSS and JS values for the PyMdownX Extensions, which means you do |
# | not need to set them up yourself. |
# | |
# | Read More: |
# | - https://www.mkdocs.org/user-guide/configuration/#markdown_extensions |
# | |
# +--------------------------------------------------------------------------------------------------------+
markdown_extensions:
- markdown.extensions.admonition:
- markdown.extensions.codehilite:
guess_lang: false
- markdown.extensions.toc:
permalink: true
- pymdownx.arithmatex:
generic: true
- attr_list
- md_in_html
- pymdownx.blocks.caption
- admonition
- pymdownx.highlight:
anchor_linenums: true
- pymdownx.superfences
- pymdownx.tabbed:
alternate_style: true
- pymdownx.details
- attr_list
- tables
#- pymdownx.b64:
#- pymdownx.betterem:
#- pymdownx.caret:
#- pymdownx.critic:
#- pymdownx.details:
#- pymdownx.emoji:
#- pymdownx.escapeall:
#- pymdownx.extra:
#- pymdownx.extrarawhtml:
#- pymdownx.highlight:
#- pymdownx.inlinehilite:
#- pymdownx.keys:
#- pymdownx.magiclink:
#- pymdownx.mark:
#- pymdownx.pathconverter:
#- pymdownx.progressbar:
#- pymdownx.smartsymbols:
#- pymdownx.snippets:
#- pymdownx.striphtml:
#- pymdownx.superfences:
#- pymdownx.tabbed:
#- pymdownx.tasklist:
#- pymdownx.tilde:
# - exporter:
# formats:
# pdf:
# enabled: !ENV [MKDOCS_EXPORTER_PDF, true]
# concurrency: 8
# stylesheets:
# - resources/stylesheets/pdf.scss
# covers:
# front: resources/templates/covers/front.html.j2
# back: resources/templates/covers/back.html.j2
# aggregator:
# enabled: true
# output: .well-known/site.pdf
# covers: all
# theme:
# name: material
# palette:
# - scheme: default
# primary: indigo
# accent: blue
# toggle:
# icon: material/brightness-7
# name: Switch to dark mode
# - scheme: slate
# primary: indigo
# accent: blue
# toggle:
# icon: material/brightness-4
# name: Switch to light mode
# features:
# - navigation.tabs
# - navigation.sections
# - navigation.top
# - content.code.copy
# - content.tabs.link
# plugins:
# - search
# markdown_extensions:

7
poetry.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Poetry 2.3.1 and should not be changed by hand.
package = []
[metadata]
lock-version = "2.1"
python-versions = ">=3.9"
content-hash = "db9b4c08b159b17b239e26c67ead7c37b82d9f9eb06550245ae3134c095f98f7"

15
pyproject.toml Normal file
View File

@@ -0,0 +1,15 @@
[tool.poetry]
name = "uLib"
version = "0.6.0"
description = "CMT Cosmic Muon Tomography project uLib python bindings"
authors = ["Andrea Rigoni Garola <andrea.rigoni@pd.infn.it>"]
readme = "README.md"
packages = [{ include = "uLib", from = "src/Python" }]
build = "build_python.py"
[tool.poetry.dependencies]
python = ">=3.9"
[build-system]
requires = ["poetry-core>=2.0.0", "pybind11>=2.6.0", "cmake>=3.12"]
build-backend = "poetry.core.masonry.api"

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,38 @@
set(HEADERS Options.h set(HEADERS
StaticInterface.h) Archives.h
Array.h
Collection.h
DataAllocator.h
Debug.h
Export.h
Function.h
Macros.h
Mpl.h
Object.h
Options.h
Serializable.h
Signal.h
Singleton.h
SmartPointer.h
StaticInterface.h
StringReader.h
Types.h
Uuid.h
Vector.h
)
set(SOURCES Options.cpp) set(SOURCES
Archives.cpp
Debug.cpp
Object.cpp
Options.cpp
Serializable.cpp
Signal.cpp
Uuid.cpp
)
set(LIBRARIES ${Boost_PROGRAM_OPTIONS_LIBRARY}) set(LIBRARIES Boost::program_options Boost::serialization)
set(libname ${PACKAGE_LIBPREFIX}Core) set(libname ${PACKAGE_LIBPREFIX}Core)
set(ULIB_SHARED_LIBRARIES ${ULIB_SHARED_LIBRARIES} ${libname} PARENT_SCOPE) set(ULIB_SHARED_LIBRARIES ${ULIB_SHARED_LIBRARIES} ${libname} PARENT_SCOPE)
@@ -14,14 +42,20 @@ add_library(${libname} SHARED ${SOURCES})
set_target_properties(${libname} PROPERTIES set_target_properties(${libname} PROPERTIES
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_SOVERSION}) SOVERSION ${PROJECT_SOVERSION})
if(USE_CUDA)
set(LIBRARIES ${LIBRARIES} CUDA::cudart)
endif()
target_link_libraries(${libname} ${LIBRARIES}) target_link_libraries(${libname} ${LIBRARIES})
install(TARGETS ${libname} install(TARGETS ${libname}
EXPORT "${PROJECT_NAME}Targets" EXPORT "${PROJECT_NAME}Targets"
RUNTIME DESTINATION ${PACKAGE_INSTALL_BIN_DIR} COMPONENT bin RUNTIME DESTINATION ${INSTALL_BIN_DIR} COMPONENT bin
LIBRARY DESTINATION ${PACKAGE_INSTALL_LIB_DIR} COMPONENT lib) LIBRARY DESTINATION ${INSTALL_LIB_DIR} COMPONENT lib)
install(FILES ${HEADERS} DESTINATION ${PACKAGE_INSTALL_INC_DIR}/Core)
install(FILES ${HEADERS} DESTINATION ${INSTALL_INC_DIR}/Core)
if(BUILD_TESTING)
include(uLibTargetMacros)
add_subdirectory(testing)
endif()

260
src/Core/DataAllocator.h Normal file
View File

@@ -0,0 +1,260 @@
/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
------------------------------------------------------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
//////////////////////////////////////////////////////////////////////////////*/
#ifndef U_MATH_DATAALLOCATOR_H
#define U_MATH_DATAALLOCATOR_H
#include <algorithm>
#include <cstring>
#include <iostream>
#include <stdexcept>
#include <vector>
#ifdef USE_CUDA
#include <cuda_runtime.h>
#include <thrust/device_vector.h>
#endif
namespace uLib {
enum class MemoryDevice { RAM, VRAM };
template <typename T> class DataAllocator {
public:
DataAllocator(size_t size = 0, bool owns_objects = true)
: m_Size(size), m_RamData(nullptr), m_VramData(nullptr),
m_Device(MemoryDevice::RAM), m_OwnsObjects(owns_objects) {
if (m_Size > 0) {
if (m_OwnsObjects)
m_RamData = new T[m_Size]();
else
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
}
}
DataAllocator(const DataAllocator<T> &other)
: m_Size(other.m_Size), m_RamData(nullptr), m_VramData(nullptr),
m_Device(other.m_Device), m_OwnsObjects(other.m_OwnsObjects) {
if (m_Size > 0) {
if (other.m_RamData) {
if (m_OwnsObjects)
m_RamData = new T[m_Size];
else
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
std::memcpy(m_RamData, other.m_RamData, m_Size * sizeof(T));
}
#ifdef USE_CUDA
if (other.m_VramData) {
cudaMalloc((void **)&m_VramData, m_Size * sizeof(T));
cudaMemcpy(m_VramData, other.m_VramData, m_Size * sizeof(T),
cudaMemcpyDeviceToDevice);
}
#endif
}
}
~DataAllocator() {
if (m_RamData) {
if (m_OwnsObjects)
delete[] m_RamData;
else
::operator delete(m_RamData);
}
#ifdef USE_CUDA
if (m_VramData) {
cudaFree(m_VramData);
}
#endif
}
DataAllocator &operator=(const DataAllocator &other) {
if (this != &other) {
m_OwnsObjects = other.m_OwnsObjects;
resize(other.m_Size);
m_Device = other.m_Device;
if (other.m_RamData) {
if (!m_RamData) {
if (m_OwnsObjects)
m_RamData = new T[m_Size];
else
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
}
std::memcpy(m_RamData, other.m_RamData, m_Size * sizeof(T));
}
#ifdef USE_CUDA
if (other.m_VramData) {
if (!m_VramData)
cudaMalloc((void **)&m_VramData, m_Size * sizeof(T));
cudaMemcpy(m_VramData, other.m_VramData, m_Size * sizeof(T),
cudaMemcpyDeviceToDevice);
}
#endif
}
return *this;
}
void MoveToRAM() {
if (m_Device == MemoryDevice::RAM)
return;
if (!m_RamData && m_Size > 0) {
if (m_OwnsObjects)
m_RamData = new T[m_Size]();
else
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
}
#ifdef USE_CUDA
if (m_VramData && m_Size > 0) {
cudaMemcpy(m_RamData, m_VramData, m_Size * sizeof(T),
cudaMemcpyDeviceToHost);
}
#endif
m_Device = MemoryDevice::RAM;
}
void MoveToVRAM() {
if (m_Device == MemoryDevice::VRAM)
return;
#ifdef USE_CUDA
if (!m_VramData && m_Size > 0) {
cudaMalloc((void **)&m_VramData, m_Size * sizeof(T));
}
if (m_RamData && m_Size > 0) {
cudaMemcpy(m_VramData, m_RamData, m_Size * sizeof(T),
cudaMemcpyHostToDevice);
}
#endif
m_Device = MemoryDevice::VRAM;
}
void resize(size_t size) {
if (m_Size == size)
return;
T *newRam = nullptr;
T *newVram = nullptr;
if (size > 0) {
if (m_OwnsObjects)
newRam = new T[size]();
else
newRam = static_cast<T *>(::operator new(size * sizeof(T)));
if (m_RamData) {
std::memcpy(newRam, m_RamData, std::min(m_Size, size) * sizeof(T));
}
#ifdef USE_CUDA
cudaMalloc((void **)&newVram, size * sizeof(T));
if (m_VramData) {
cudaMemcpy(newVram, m_VramData, std::min(m_Size, size) * sizeof(T),
cudaMemcpyDeviceToDevice);
}
#endif
}
if (m_RamData) {
if (m_OwnsObjects)
delete[] m_RamData;
else
::operator delete(m_RamData);
}
#ifdef USE_CUDA
if (m_VramData)
cudaFree(m_VramData);
#endif
m_Size = size;
m_RamData = newRam;
m_VramData = newVram;
}
size_t size() const { return m_Size; }
T &at(size_t index) {
MoveToRAM();
if (index >= m_Size)
throw std::out_of_range("Index out of range");
return m_RamData[index];
}
const T &at(size_t index) const {
const_cast<DataAllocator *>(this)->MoveToRAM();
if (index >= m_Size)
throw std::out_of_range("Index out of range");
return m_RamData[index];
}
T &operator[](size_t index) {
MoveToRAM();
return m_RamData[index];
}
const T &operator[](size_t index) const {
const_cast<DataAllocator *>(this)->MoveToRAM();
return m_RamData[index];
}
T *data() { return (m_Device == MemoryDevice::RAM) ? m_RamData : m_VramData; }
const T *data() const {
return (m_Device == MemoryDevice::RAM) ? m_RamData : m_VramData;
}
T *GetRAMData() { return m_RamData; }
const T *GetRAMData() const { return m_RamData; }
T *GetVRAMData() { return m_VramData; }
const T *GetVRAMData() const { return m_VramData; }
MemoryDevice GetDevice() const { return m_Device; }
// Iterator support for RAM operations
T *begin() {
MoveToRAM();
return m_RamData;
}
T *end() {
MoveToRAM();
return m_RamData + m_Size;
}
const T *begin() const {
const_cast<DataAllocator *>(this)->MoveToRAM();
return m_RamData;
}
const T *end() const {
const_cast<DataAllocator *>(this)->MoveToRAM();
return m_RamData + m_Size;
}
private:
size_t m_Size;
T *m_RamData;
T *m_VramData;
MemoryDevice m_Device;
bool m_OwnsObjects;
};
} // namespace uLib
#endif // U_MATH_DATAALLOCATOR_H

View File

@@ -23,95 +23,85 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef U_CORE_EXPORT_H #ifndef U_CORE_EXPORT_H
#define U_CORE_EXPORT_H #define U_CORE_EXPORT_H
#include <utility>
#include <cstddef> // NULL #include <cstddef> // NULL
#include <iostream> #include <iostream>
#include <utility>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/static_assert.hpp>
#include <boost/preprocessor/stringize.hpp> #include <boost/preprocessor/stringize.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_polymorphic.hpp> #include <boost/type_traits/is_polymorphic.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/and.hpp> #include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp> #include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp> #include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/serialization/extended_type_info.hpp> // for guid_defined only
#include <boost/serialization/static_warning.hpp>
#include <boost/serialization/assume_abstract.hpp> #include <boost/serialization/assume_abstract.hpp>
#include <boost/serialization/extended_type_info.hpp> // for guid_defined only
#include <boost/serialization/force_include.hpp> #include <boost/serialization/force_include.hpp>
#include <boost/serialization/singleton.hpp> #include <boost/serialization/singleton.hpp>
#include <boost/serialization/static_warning.hpp>
#include <boost/archive/detail/register_archive.hpp> #include <boost/archive/detail/register_archive.hpp>
#include "Core/Archives.h" #include "Core/Archives.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace uLib { namespace uLib {
namespace Archive { namespace Archive {
namespace detail { namespace detail {
namespace extra_detail { namespace extra_detail {
template<class T> template <class T> struct guid_initializer {
struct guid_initializer void export_guid(boost::mpl::false_) const {
{ // generates the statically-initialized objects whose constructors
void export_guid(mpl::false_) const { // register the information allowing serialization of T objects
// generates the statically-initialized objects whose constructors // through pointers to their base classes.
// register the information allowing serialization of T objects boost::archive::detail::instantiate_ptr_serialization(
// through pointers to their base classes. (T *)0, 0, uLib::Archive::detail::adl_tag());
boost::archive::detail:: }
instantiate_ptr_serialization((T*)0, 0, void export_guid(boost::mpl::true_) const {}
uLib::Archive::detail::adl_tag()); guid_initializer const &export_guid() const {
} BOOST_STATIC_WARNING(boost::is_polymorphic<T>::value);
void export_guid(mpl::true_) const { // note: exporting an abstract base class will have no effect
} // and cannot be used to instantitiate serialization code
guid_initializer const & export_guid() const { // (one might be using this in a DLL to instantiate code)
BOOST_STATIC_WARNING(boost::is_polymorphic< T >::value); // BOOST_STATIC_WARNING(! boost::serialization::is_abstract< T >::value);
// note: exporting an abstract base class will have no effect export_guid(boost::serialization::is_abstract<T>());
// and cannot be used to instantitiate serialization code return *this;
// (one might be using this in a DLL to instantiate code) }
//BOOST_STATIC_WARNING(! boost::serialization::is_abstract< T >::value);
export_guid(boost::serialization::is_abstract< T >());
return *this;
}
}; };
template<typename T> template <typename T> struct init_guid;
struct init_guid;
} // anonymous } // namespace extra_detail
} // namespace detail } // namespace detail
} // namespace Archive } // namespace Archive
} // namespace uLib } // namespace uLib
#define ULIB_CLASS_EXPORT_IMPLEMENT(T) \
namespace uLib { \
#define ULIB_CLASS_EXPORT_IMPLEMENT(T) \ namespace Archive { \
namespace uLib { \ namespace detail { \
namespace Archive { \ namespace extra_detail { \
namespace detail { \ template <> struct init_guid<T> { \
namespace extra_detail { \ static guid_initializer<T> const &g; \
template<> \ }; \
struct init_guid< T > { \ guid_initializer<T> const &init_guid<T>::g = \
static guid_initializer< T > const & g; \ ::boost::serialization::singleton< \
}; \ guid_initializer<T>>::get_mutable_instance() \
guid_initializer< T > const & init_guid< T >::g = \ .export_guid(); \
::boost::serialization::singleton< \ } \
guid_initializer< T > \ } \
>::get_mutable_instance().export_guid(); \ } \
}}}} \ } \
/**/ /**/
#endif // EXPORT_H #endif // EXPORT_H

View File

@@ -14,7 +14,6 @@ library_include_HEADERS = \
Macros.h \ Macros.h \
Mpl.h \ Mpl.h \
Object.h \ Object.h \
ObjectProps.h \
Options.h \ Options.h \
Serializable.h \ Serializable.h \
Signal.h \ Signal.h \

View File

@@ -23,178 +23,128 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include "config.h" #include "config.h"
#include "Object.h" #include "Object.h"
#include "Vector.h" #include "Vector.h"
#include "boost/archive/polymorphic_xml_oarchive.hpp"
#include "boost/archive/polymorphic_xml_iarchive.hpp"
#include "boost/archive/polymorphic_text_oarchive.hpp"
#include "boost/archive/polymorphic_text_iarchive.hpp"
#include "boost/archive/polymorphic_binary_oarchive.hpp"
#include "boost/archive/polymorphic_binary_iarchive.hpp" #include "boost/archive/polymorphic_binary_iarchive.hpp"
#include "boost/archive/polymorphic_binary_oarchive.hpp"
#include "boost/archive/polymorphic_text_iarchive.hpp"
#include "boost/archive/polymorphic_text_oarchive.hpp"
#include "boost/archive/polymorphic_xml_iarchive.hpp"
#include "boost/archive/polymorphic_xml_oarchive.hpp"
namespace uLib { namespace uLib {
const char *Version::PackageName = PACKAGE_NAME;
const char *Version::PackageName = PACKAGE_NAME;
const char *Version::VersionNumber = PACKAGE_VERSION; const char *Version::VersionNumber = PACKAGE_VERSION;
const char *Version::Release = "x"; //SVN_REVISION; const char *Version::Release = "x"; // SVN_REVISION;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Object Private // // Object Private //
class ObjectPrivate { class ObjectPrivate {
public: public:
struct Signal {
GenericMFPtr sigptr;
std::string sigstr;
SignalBase *signal;
};
struct Signal { struct Slot {
GenericMFPtr sigptr; GenericMFPtr sloptr;
std::string sigstr; std::string slostr;
SignalBase *signal; };
};
struct Slot { Vector<Signal> sigv;
GenericMFPtr sloptr; Vector<Slot> slov;
std::string slostr;
};
Vector<Signal> sigv;
Vector<Slot> slov;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// OBJECT IMPLEMENTATION // OBJECT IMPLEMENTATION
Object::Object() : d(new ObjectPrivate) {}
Object::Object(const Object &copy) : d(new ObjectPrivate(*copy.d)) {}
Object::Object() : Object::~Object() { delete d; }
d(new ObjectPrivate)
{}
Object::Object(const Object &copy) : void Object::DeepCopy(const Object &copy) {
ObjectPropable(copy), // should lock to be tread safe //
d(new ObjectPrivate(*copy.d)) memcpy(d, copy.d, sizeof(ObjectPrivate));
{} // ERROR! does not copy parameters ... <<<< FIXXXXX
Object::~Object() {
delete d;
} }
void Object::DeepCopy(const Object &copy) void Object::SaveXml(std::ostream &os, Object &ob) {
{ Archive::xml_oarchive ar(os);
// should lock to be tread safe // ar << boost::serialization::make_nvp("Object", ob);
memcpy(d,copy.d,sizeof(ObjectPrivate));
// ERROR! does not copy parameters ... <<<< FIXXXXX
} }
void Object::LoadXml(std::istream &is, Object &ob) {
Archive::xml_iarchive ar(is);
ar >> boost::serialization::make_nvp("Object", ob);
void Object::SaveXml(std::ostream &os, Object &ob)
{
Archive::xml_oarchive ar(os);
ar << boost::serialization::make_nvp("Object",ob);
} }
void Object::LoadXml(std::istream &is, Object &ob)
{
Archive::xml_iarchive ar(is);
ar >> boost::serialization::make_nvp("Object",ob);
}
// FINIRE // FINIRE
void Object::SaveConfig(std::ostream &os, int version) void Object::SaveConfig(std::ostream &os, int version) {
{ Archive::xml_oarchive ar(os);
Archive::xml_oarchive ar(os);
ObjectPropable::serialize(ar,0);
} }
void Object::LoadConfig(std::istream &is, int version) void Object::LoadConfig(std::istream &is, int version) {
{ Archive::xml_iarchive ar(is);
if(!props()) this->init_properties();
Archive::xml_iarchive ar(is);
ObjectPropable::serialize(ar,0);
} }
void Object::PrintSelf(std::ostream &o) const {
o << "OBJECT signals: ------------------\n";
Vector<ObjectPrivate::Signal>::Iterator itr;
for (itr = d->sigv.begin(); itr < d->sigv.end(); itr++) {
void Object::PrintSelf(std::ostream &o) const o << " signal:[ " << itr->sigstr << " ]\n";
{ }
o << "OBJECT signals: ------------------\n"; o << "--------------------------------------\n\n";
Vector<ObjectPrivate::Signal>::Iterator itr;
for(itr = d->sigv.begin(); itr<d->sigv.end(); itr++)
{
o << " signal:[ " << itr->sigstr << " ]\n";
}
o << "--------------------------------------\n\n";
} }
bool Object::addSignalImpl(SignalBase *sig, GenericMFPtr fptr,
bool Object::addSignalImpl(SignalBase *sig, GenericMFPtr fptr, const char *name) const char *name) {
{ ObjectPrivate::Signal s = {fptr, std::string(name), sig};
ObjectPrivate::Signal s = {fptr,std::string(name),sig}; d->sigv.push_back(s);
d->sigv.push_back(s); return true;
} }
bool Object::addSlotImpl(GenericMFPtr fptr, const char *name) bool Object::addSlotImpl(GenericMFPtr fptr, const char *name) {
{ ObjectPrivate::Slot s = {fptr, std::string(name)};
ObjectPrivate::Slot s = {fptr,std::string(name)}; d->slov.push_back(s);
d->slov.push_back(s); return true;
} }
SignalBase *Object::findSignalImpl(const GenericMFPtr &fptr) const SignalBase *Object::findSignalImpl(const GenericMFPtr &fptr) const {
{ for (int i = 0; i < d->sigv.size(); ++i) {
for(int i=0; i<d->sigv.size(); ++i) if (d->sigv[i].sigptr == fptr)
{ return d->sigv[i].signal;
if(d->sigv[i].sigptr == fptr) }
return d->sigv[i].signal; return NULL;
}
return NULL;
} }
SignalBase *Object::findSignalImpl(const char *name) const SignalBase *Object::findSignalImpl(const char *name) const {
{ std::string in(name);
std::string in(name); for (int i = 0; i < d->sigv.size(); ++i) {
for(int i=0; i<d->sigv.size(); ++i) if (d->sigv[i].sigstr == in)
{ return d->sigv[i].signal;
if(d->sigv[i].sigstr == in) }
return d->sigv[i].signal; return NULL;
}
return NULL;
} }
GenericMFPtr *Object::findSlotImpl(const char *name) const GenericMFPtr *Object::findSlotImpl(const char *name) const {
{ std::string in(name);
std::string in(name); for (int i = 0; i < d->slov.size(); ++i) {
for(int i=0; i<d->slov.size(); ++i) if (d->slov[i].slostr == in)
{ return &d->slov[i].sloptr;
if(d->slov[i].slostr == in) }
return &d->slov[i].sloptr; return NULL;
}
return NULL;
} }
// std::ostream & // std::ostream &
// operator << (std::ostream &os, uLib::Object &ob) // operator << (std::ostream &os, uLib::Object &ob)
// { // {
@@ -218,10 +168,4 @@ GenericMFPtr *Object::findSlotImpl(const char *name) const
// return is; // return is;
// } // }
} // namespace uLib
} // uLib

View File

@@ -23,200 +23,185 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef U_CORE_OBJECT_H #ifndef U_CORE_OBJECT_H
#define U_CORE_OBJECT_H #define U_CORE_OBJECT_H
#include <iostream> #include <iostream>
// WARNING: COPILE ERROR if this goes after mpl/vector // // WARNING: COPILE ERROR if this goes after mpl/vector //
//#include "Core/Vector.h" // #include "Core/Vector.h"
#include "Core/Types.h"
#include "Core/Debug.h" #include "Core/Debug.h"
#include "Core/Types.h"
#include "Core/Function.h" #include "Core/Function.h"
#include "Core/Signal.h" #include "Core/Signal.h"
#include "Core/Mpl.h" #include "Core/Mpl.h"
#include "Core/Serializable.h" #include "Core/Serializable.h"
#include "Core/ObjectProps.h"
#include "Core/Uuid.h" #include "Core/Uuid.h"
namespace boost { namespace boost {
namespace archive { namespace archive {
class polymorphic_iarchive; class polymorphic_iarchive;
class polymorphic_oarchive; class polymorphic_oarchive;
} // archive } // namespace archive
} // boost } // namespace boost
namespace uLib { namespace uLib {
class Version { class Version {
public: public:
static const char *PackageName; static const char *PackageName;
static const char *VersionNumber; static const char *VersionNumber;
static const char *Release; static const char *Release;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//// OBJECT //////////////////////////////////////////////////////////////////// //// OBJECT ////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/** /**
* @brief Object class is the object base implementation for uLib Framework. * @brief Object class is the object base implementation for uLib Framework.
*/ */
class Object : public ObjectPropable class Object {
{
public: public:
// std::string name; // std::string name;
// void PrintName() { std::cout << "Ob name: " << name << "\n"; } // void PrintName() { std::cout << "Ob name: " << name << "\n"; }
Object(); Object();
Object(const Object &copy); Object(const Object &copy);
~Object(); ~Object();
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// PARAMETERS // // PARAMETERS //
// FIXX !!! // FIXX !!!
virtual void DeepCopy(const Object &copy); virtual void DeepCopy(const Object &copy);
////////////////////////////////////////////////////////////////////////////
// SERIALIZATION //
//////////////////////////////////////////////////////////////////////////// template <class ArchiveT>
// SERIALIZATION // void serialize(ArchiveT &ar, const unsigned int version) {}
template <class ArchiveT>
void save_override(ArchiveT &ar, const unsigned int version) {}
template <class ArchiveT> void serialize(ArchiveT &ar, const unsigned int version) { void SaveConfig(std::ostream &os, int version = 0);
ObjectPropable::serialize(ar,version); void LoadConfig(std::istream &is, int version = 0);
static void SaveXml(std::ostream &os, Object &ob);
static void LoadXml(std::istream &is, Object &ob);
////////////////////////////////////////////////////////////////////////////
// SIGNALS //
// Qt4 style connector //
static bool connect(const Object *ob1, const char *signal_name,
const Object *receiver, const char *slot_name) {
// // NOT WORKING YET //
// 1) find slot pointer from name
// SignalBase *sig = ob1->findSignal(signal_name);
// GenericMFPtr *slo = receiver->findSlot(slot_name);
// if(sig && slo)
// return Object::connect(sig,slo->operator ()(),receiver);
// else return false;
return false;
}
// Qt5 style connector //
template <typename Func1, typename Func2>
static bool
connect(typename FunctionPointer<Func1>::Object *sender, Func1 sigf,
typename FunctionPointer<Func2>::Object *receiver, Func2 slof) {
SignalBase *sigb = sender->findOrAddSignal(sigf);
ConnectSignal<typename FunctionPointer<Func1>::SignalSignature>(sigb, slof,
receiver);
return true;
}
template <typename FuncT>
static inline bool connect(SignalBase *sigb, FuncT slof, Object *receiver) {
ConnectSignal<typename FunctionPointer<FuncT>::SignalSignature>(sigb, slof,
receiver);
return true;
}
template <typename FuncT>
inline
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type *
addSignal(FuncT fun, const char *name) {
typedef
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type
SigT;
SignalBase *sig = NewSignal(fun);
addSignalImpl(sig, fun, name);
return (SigT *)sig;
}
template <typename FuncT> inline bool addSlot(FuncT fun, const char *name) {
return this->addSlotImpl(GenericMFPtr(fun), name);
}
template <typename FuncT>
inline
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type *
findSignal(FuncT fptr) {
typedef
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type
SigT;
return (SigT *)findSignalImpl(GenericMFPtr(fptr));
}
template <typename FuncT>
inline
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type *
findOrAddSignal(FuncT fptr) {
typedef
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type
SigT;
SignalBase *sig = findSignalImpl(GenericMFPtr(fptr));
if (!sig) {
sig = NewSignal(fptr);
addSignalImpl(sig, fptr, "signal_name_to_be_implemented");
} }
template <class ArchiveT> void save_override(ArchiveT &ar,const unsigned int version) {} return (SigT *)sig;
}
void SaveConfig(std::ostream &os, int version = 0); inline SignalBase *findSignal(const char *name) const {
void LoadConfig(std::istream &is, int version = 0); return findSignalImpl(name);
}
static void SaveXml(std::ostream &os, Object &ob); inline GenericMFPtr *findSlot(const char *name) const {
static void LoadXml(std::istream &is, Object &ob); return findSlotImpl(name);
}
void PrintSelf(std::ostream &o) const;
inline const Object &operator=(const Object &copy) {
//////////////////////////////////////////////////////////////////////////// this->DeepCopy(copy);
// SIGNALS // return *this;
}
// Qt4 style connector //
static bool connect(const Object *ob1, const char *signal_name, const Object *receiver, const char *slot_name) {
// // NOT WORKING YET //
// 1) find slot pointer from name
// SignalBase *sig = ob1->findSignal(signal_name);
// GenericMFPtr *slo = receiver->findSlot(slot_name);
// if(sig && slo)
// return Object::connect(sig,slo->operator ()(),receiver);
// else return false;
}
// Qt5 style connector //
template <typename Func1, typename Func2>
static bool connect( typename FunctionPointer<Func1>::Object *sender, Func1 sigf,
typename FunctionPointer<Func2>::Object *receiver, Func2 slof)
{
SignalBase *sigb = sender->findOrAddSignal(sigf);
typedef boost::signals2::signal<typename FunctionPointer<Func2>::SignalSignature> SigT;
ConnectSignal(sigb,slof,receiver);
}
template <typename FuncT>
static inline bool connect(SignalBase *sigb, FuncT slof, Object *receiver) {
ConnectSignal(sigb,slof,receiver);
}
template< typename FuncT >
inline typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type *
addSignal(FuncT fun, const char *name) {
typedef typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type SigT;
SignalBase *sig = NewSignal(fun);
addSignalImpl(sig,fun,name);
return (SigT *)sig;
}
template< typename FuncT>
inline bool addSlot(FuncT fun, const char *name) {
this->addSlotImpl(GenericMFPtr(fun),name);
}
template < typename FuncT >
inline typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type *
findSignal(FuncT fptr)
{
typedef typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type SigT;
return (SigT *)findSignalImpl(GenericMFPtr(fptr));
}
template < typename FuncT >
inline typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type *
findOrAddSignal(FuncT fptr)
{
typedef typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type SigT;
SignalBase *sig = findSignalImpl(GenericMFPtr(fptr));
if(!sig) {
sig = NewSignal(fptr);
addSignalImpl(sig,fptr,"signal_name_to_be_implemented");
}
return (SigT *)sig;
}
inline SignalBase *
findSignal(const char *name) const
{
return findSignalImpl(name);
}
inline GenericMFPtr *
findSlot(const char *name) const
{
return findSlotImpl(name);
}
void PrintSelf(std::ostream &o) const;
inline const Object& operator = (const Object &copy)
{ this->DeepCopy(copy); return *this; }
private: private:
bool addSignalImpl(SignalBase *sig, GenericMFPtr fptr, const char *name); bool addSignalImpl(SignalBase *sig, GenericMFPtr fptr, const char *name);
bool addSlotImpl(GenericMFPtr fptr, const char *name); bool addSlotImpl(GenericMFPtr fptr, const char *name);
SignalBase *findSignalImpl(const GenericMFPtr &fptr) const; SignalBase *findSignalImpl(const GenericMFPtr &fptr) const;
SignalBase *findSignalImpl(const char *name) const; SignalBase *findSignalImpl(const char *name) const;
GenericMFPtr *findSlotImpl(const char *name) const; GenericMFPtr *findSlotImpl(const char *name) const;
friend class boost::serialization::access; friend class boost::serialization::access;
friend class ObjectPrivate; friend class ObjectPrivate;
class ObjectPrivate *d; class ObjectPrivate *d;
}; };
} // namespace uLib
} // uLib
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//std::ostream & operator << (std::ostream &os, uLib::Object &ob); // std::ostream & operator << (std::ostream &os, uLib::Object &ob);
//std::ostream & operator << (std::ostream &os, uLib::Object *ob); // std::ostream & operator << (std::ostream &os, uLib::Object *ob);
//std::istream & operator >> (std::istream &is, uLib::Object &ob); // std::istream & operator >> (std::istream &is, uLib::Object &ob);
#endif // U_OBJECT_H #endif // U_OBJECT_H

View File

@@ -1,278 +0,0 @@
/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
------------------------------------------------------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
//////////////////////////////////////////////////////////////////////////////*/
#ifndef U_OBJECTPROPS_H
#define U_OBJECTPROPS_H
#include <boost/algorithm/string/replace.hpp>
#include <Core/Mpl.h>
#include <Core/Types.h>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// MACROS //
#define ULIB_props() \
public: struct ObjectProps; \
virtual void init_properties(); \
inline struct ObjectProps &p() { /* static const unsigned int offset = props_offset(this); */ \
/* NON FUNZIA! return * (struct ObjectProps *)(reinterpret_cast<char*>(props())+offset); */ \
return *props()->ptr<ObjectProps>(); } \
typedef uLib::mpl::bool_<true>::type propable_trait; \
public: struct DLL_PUBLIC ObjectProps
#define properties() ULIB_props()
#define default(vlaue)
#define $$ p()
#define $(_name) props_ref<_name>()
#define $_init() \
if(props(this)) return; \
props_new(this); \
uLib::detail::ObjectProps::initializer::init_object_baselist(this);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
namespace boost {
namespace serialization {
class access;
}
}
namespace uLib {
namespace detail {
struct ObjectProps {
/** Define a trait has_member to find if an Object is Propable*/
BOOST_MPL_HAS_XXX_TRAIT_DEF(propable_trait)
/** IsA ProbapleObject Implementation Template */
template <class T>
struct IsA : has_propable_trait<T> {};
/** Lambda to get Props member type */
template <class T>
struct props_type {
typedef typename T::ObjectProps type;
};
template <typename T>
struct get_props {
/** CFList has result but this method check for has BaseList */
typedef typename detail::TypeIntrospection::child_first<T>::type CFTypeList;
/** Filter List items that have not Propable feature */
typedef typename mpl::filter_view< CFTypeList, IsA<mpl::_> >::type FilteredCFTypeList;
/** Get Props from each Parent in Seq */
typedef typename mpl::transform_view< FilteredCFTypeList, props_type<mpl::_> >::type type;
// qui sotto ho un problema che ho temporaneamente tamponato //
// ovvero ho usato child_first_impl per ottenere la lista delle basi //
// vorrei farlo facendo un pop_back ma non va forse perche il tipo //
// non e' corretto. //
/** Get Parent list from CFTypeList */
typedef typename detail::TypeIntrospection::child_first_impl<T>::Childs CFBaseList;
/** Filter Parents that have not Propable feature */
typedef typename mpl::filter_view< CFBaseList, IsA<mpl::_> >::type FilteredCFBaseList;
};
// TODO: convert to pp const value,
// (non so se sia possibile con il dinamic casting intanto funziona cosi' )
template <typename T1, typename T2>
static unsigned int measure_offset(T1 base, T2 derived) {
return reinterpret_cast<char*>(derived) - reinterpret_cast<char*>(base);
}
struct initializer {
template <class _ObjectT>
struct lambda_init_object {
_ObjectT *o;
lambda_init_object(_ObjectT *o) : o(o) {}
template<class T> void operator()(T) {
o->T::init_properties();
}
};
/**
* This calls the internal init_properties() virtual function for each
* object parent defined in BaseList only if it is propable
*/
template <class T>
static void init_object_baselist(T *o) {
typedef typename uLib::detail::ObjectProps::get_props<T>::FilteredCFBaseList CFBaseList;
mpl::for_each<CFBaseList>(lambda_init_object<T>(o));
}
/**
* This calls the internal init_properties() virtual function only if
* object is propable ( implementation if not propable )
*/
template <class T>
static
typename boost::enable_if<mpl::not_<IsA<T> >,void>::type
init_object(T *o) {
; // do nothing //
}
/**
* This calls the internal init_properties() virtual function only if
* object is propable ( implementation if propable )
*/
template <class T>
static
typename boost::enable_if<IsA<T>,void>::type
init_object(T *o) {
o->init_properties();
}
};
template <class ThisClass, class Archive>
struct serialize_baselist {
ThisClass & m_object;
Archive & m_ar;
serialize_baselist(ThisClass &o, Archive &ar) : m_object(o), m_ar(ar) {}
template <class T> void operator()(T &o) {
// T is taken fron get_props<BaseList>::FilteredPList types to get
// type_info_name that is the type name defined by Type macro
typedef typename props_type<T>::type PType;
std::string name(TypeIntrospection::access<T>::type_info::name);
boost::algorithm::replace_all(name,"::","_");
m_ar & boost::serialization::make_nvp(
name.c_str() ,
boost::serialization::base_object<PType>(m_object));
}
};
};
} // detail
struct ObjectPropsBase {
virtual ~ObjectPropsBase() {}
virtual ObjectPropsBase *copy() = 0;
template <class T> inline T *ptr() { return dynamic_cast<T*>(this); }
template<class ArchiveT> void serialize(ArchiveT &ar, const unsigned int version) {}
};
template <class T>
struct ObjectPropsImpl :
ObjectPropsBase,
ULIB_MPL_INHERIT_NOFOLD_SEQ(typename uLib::detail::ObjectProps::get_props<T>::type)
{
typedef ObjectPropsImpl<T> ThisClass;
typedef typename uLib::detail::ObjectProps::get_props<T>::type CFList;
typedef typename uLib::detail::ObjectProps::get_props<T>::FilteredCFTypeList FilteredCFTypeList;
ObjectPropsBase *copy() { return new ThisClass(*this); }
template<class ArchiveT> void serialize(ArchiveT &ar, const unsigned int version) {
boost::serialization::void_cast_register<ThisClass,ObjectPropsBase>();
mpl::for_each<FilteredCFTypeList>(detail::ObjectProps::serialize_baselist<ThisClass,ArchiveT>(*this,ar));
}
};
class ObjectPropable {
ObjectPropsBase *m_props;
friend class uLib::detail::ObjectProps;
friend class boost::serialization::access;
public:
ObjectPropable() : m_props(NULL) {}
ObjectPropable(const ObjectPropable &c) { if(c.m_props) m_props = c.m_props->copy(); else m_props = NULL; }
~ObjectPropable() { if(m_props) delete m_props; }
template <class T> inline typename T::ObjectProps& props_ref() const { if(m_props) return *m_props->ptr<typename T::ObjectProps>(); else exit(1); }
template <class T> inline typename T::ObjectProps* props(T *ptr = NULL) const { if(m_props) return m_props->ptr<typename T::ObjectProps>(); else return NULL; }
protected:
ObjectPropsBase *props() const { return m_props; }
template <class T> inline void props_new(T* ptr = NULL) { if(!m_props) m_props = new ObjectPropsImpl<T>; }
/** NOT working dynamic cache casting */
template <class T> inline unsigned int props_offset(T *ptr) const
{ if(m_props) return detail::ObjectProps::measure_offset(m_props,m_props->ptr<T>()); else return -1; }
template<class ArchiveT> void serialize(ArchiveT &ar, const unsigned int version) {
if(m_props) ar & boost::serialization::make_nvp("properties",m_props);
}
public:
/**
* ObjectPropable is not directly propable itself to prevent Basclass
* duplication in inherit_nofold. And for the same reason ANY VIRTUAL BASE
* SHOULD NOT BE PROPABLE
*/
virtual void init_properties() {}
};
} // uLib
#endif // U_OBJECTPROPS_H

View File

@@ -31,6 +31,9 @@
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
//class boost::program_options::error_with_option_name; //class boost::program_options::error_with_option_name;
//template<> boost::program_options::typed_value<int> boost::program_options::value<int>(); //template<> boost::program_options::typed_value<int> boost::program_options::value<int>();
@@ -74,6 +77,23 @@ void Options::parse_config_file(const char *fname)
} }
} }
void Options::save_config_file(const char *fname) {
std::ofstream os;
os.open(fname);
using boost::property_tree::ptree;
ptree root;
std::cout << m_configuration << "\n";
std::cout << m_global << "\n";
write_ini( std::cout, root );
}
bool Options::count(const char *str) const bool Options::count(const char *str) const
{ {
return (m_vm.count(str)); return (m_vm.count(str));

View File

@@ -160,6 +160,8 @@ public:
void parse_config_file(const char *fname); void parse_config_file(const char *fname);
void save_config_file(const char *fname);
template <typename T> template <typename T>
static inline boost::program_options::typed_value<T>* value(T *v, T dvalue) { static inline boost::program_options::typed_value<T>* value(T *v, T dvalue) {
boost::program_options::typed_value<T> *r = boost::program_options::value<T>(v); boost::program_options::typed_value<T> *r = boost::program_options::value<T>(v);

View File

@@ -23,8 +23,6 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef U_SERIALIZABLE_H #ifndef U_SERIALIZABLE_H
#define U_SERIALIZABLE_H #define U_SERIALIZABLE_H
@@ -38,9 +36,6 @@ TODO:
*/ */
#include <boost/serialization/access.hpp> #include <boost/serialization/access.hpp>
#include <boost/serialization/export.hpp> #include <boost/serialization/export.hpp>
@@ -48,26 +43,22 @@ TODO:
#include <boost/mpl/remove_if.hpp> #include <boost/mpl/remove_if.hpp>
#include <boost/serialization/nvp.hpp> #include <boost/serialization/nvp.hpp>
//#include <boost/archive/xml_iarchive.hpp> // #include <boost/archive/xml_iarchive.hpp>
//#include <boost/archive/xml_oarchive.hpp> // #include <boost/archive/xml_oarchive.hpp>
//#include <boost/archive/text_iarchive.hpp> // #include <boost/archive/text_iarchive.hpp>
//#include <boost/archive/text_oarchive.hpp> // #include <boost/archive/text_oarchive.hpp>
//#include "boost/archive/polymorphic_iarchive.hpp" // #include "boost/archive/polymorphic_iarchive.hpp"
//#include "boost/archive/polymorphic_oarchive.hpp" // #include "boost/archive/polymorphic_oarchive.hpp"
#include <boost/preprocessor/comma_if.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/inc.hpp>
#include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/comma_if.hpp>
#include <boost/preprocessor/inc.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/tuple/to_seq.hpp> #include <boost/preprocessor/tuple/to_seq.hpp>
#include "Core/Mpl.h"
#include "Core/ObjectProps.h"
#include "Core/Archives.h" #include "Core/Archives.h"
#include "Core/Export.h" #include "Core/Export.h"
#include "Core/Mpl.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -80,63 +71,47 @@ namespace serialization {
// ACCESS 2 // // ACCESS 2 //
template <class T> struct access2 {}; template <class T> struct access2 {};
// NON FUNZIONA ... SISTEMARE !!!! // ------------------------------------------ // NON FUNZIONA ... SISTEMARE !!!! // ------------------------------------------
template<class T> template <class T> class hrp : public wrapper_traits<const hrp<T>> {
class hrp : const char *m_name;
public wrapper_traits<const hrp< T > > T *m_value;
{ std::string *m_str;
const char *m_name;
T *m_value;
std::string *m_str;
public: public:
explicit hrp(const char * name_, T &t) : explicit hrp(const char *name_, T &t)
m_str(new std::string), : m_str(new std::string), m_name(name_), m_value(&t) {}
m_name(name_), m_value(&t) {}
const char * name() const { const char *name() const { return this->m_name; }
return this->m_name;
}
template <class Archivex>
template<class Archivex> void save(Archivex &ar, const unsigned int /* file_version */) const {
void save( Archivex & ar, const unsigned int /* file_version */) const { //// ar.operator<<(const_value());
//// ar.operator<<(const_value()); // std::stringstream ss;
// std::stringstream ss; // uLib::Archive::hrt_oarchive har(ss);
// uLib::Archive::hrt_oarchive har(ss); // har << make_nvp(m_name,*m_value);
// har << make_nvp(m_name,*m_value); // // (*m_str) = ss.str();
// // (*m_str) = ss.str(); //// ar.operator << (make_nvp(m_name, ss.str());
//// ar.operator << (make_nvp(m_name, ss.str()); }
} template <class Archivex>
template<class Archivex> void load(Archivex &ar, const unsigned int /* file_version */) {
void load( Archivex & ar, const unsigned int /* file_version */) { // ar.operator>>(value());
// ar.operator>>(value()); }
} BOOST_SERIALIZATION_SPLIT_MEMBER()
BOOST_SERIALIZATION_SPLIT_MEMBER()
}; };
template <class T>
template<class T>
inline inline
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
const const
#endif #endif
hrp< T > make_hrp(const char * name, T & t){ hrp<T> make_hrp(const char *name, T &t) {
return hrp< T >(name, t); return hrp<T>(name, t);
} }
#define HRP(name) \ #define HRP(name) boost::serialization::make_hrp(BOOST_PP_STRINGIZE(name), name)
boost::serialization::make_hrp(BOOST_PP_STRINGIZE(name), name)
} // serialization
} // boost
} // namespace serialization
} // namespace boost
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -151,9 +126,7 @@ hrp< T > make_hrp(const char * name, T & t){
namespace uLib { namespace uLib {
#define _AR_OP(r, data, elem) data &BOOST_SERIALIZATION_BASE_OBJECT_NVP(elem);
#define _AR_OP(r,data,elem) data&BOOST_SERIALIZATION_BASE_OBJECT_NVP(elem);
#define NVP(data) BOOST_SERIALIZATION_NVP(data) #define NVP(data) BOOST_SERIALIZATION_NVP(data)
@@ -166,51 +139,53 @@ namespace uLib {
// SO LEAVE ULIB_CFG_INTRUSIVE_SERIALIZATION NOT DEFINED // SO LEAVE ULIB_CFG_INTRUSIVE_SERIALIZATION NOT DEFINED
#ifdef ULIB_CFG_INTRUSIVE_SERIALIZATION_OBJECT #ifdef ULIB_CFG_INTRUSIVE_SERIALIZATION_OBJECT
# define ULIB_SERIALIZABLE_OBJECT _ULIB_DETAIL_INTRUSIVE_SERIALIZABLE_OBJECT #define ULIB_SERIALIZABLE_OBJECT _ULIB_DETAIL_INTRUSIVE_SERIALIZABLE_OBJECT
# define ULIB_SERIALIZE_OBJECT(_Ob,...) _ULIB_DETAIL_INTRUSIVE_SERIALIZE_OBJECT(_Ob,__VA_ARGS__) #define ULIB_SERIALIZE_OBJECT(_Ob, ...) \
# define _AR_(_name) _ULIB_DETAIL_INTRUSIVE_AR_(_name) _ULIB_DETAIL_INTRUSIVE_SERIALIZE_OBJECT(_Ob, __VA_ARGS__)
#define _AR_(_name) _ULIB_DETAIL_INTRUSIVE_AR_(_name)
#else #else
# define ULIB_SERIALIZABLE(_Ob) _ULIB_DETAIL_UNINTRUSIVE_SERIALIZABLE(_Ob) \ #define ULIB_SERIALIZABLE(_Ob) \
ULIB_CLASS_EXPORT_KEY(_Ob) _ULIB_DETAIL_UNINTRUSIVE_SERIALIZABLE(_Ob) \
# define ULIB_SERIALIZE(_Ob,...) _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE(_Ob) ULIB_CLASS_EXPORT_KEY(_Ob)
# define ULIB_SERIALIZE_DERIVED(_Ob,...) _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_DERIVED(_Ob,__VA_ARGS__) #define ULIB_SERIALIZE(_Ob, ...) _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE(_Ob)
# define ULIB_SERIALIZABLE_OBJECT(_Ob) _ULIB_DETAIL_UNINTRUSIVE_SERIALIZABLE_OBJECT(_Ob) \ #define ULIB_SERIALIZE_DERIVED(_Ob, ...) \
ULIB_CLASS_EXPORT_OBJECT_KEY(_Ob) _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_DERIVED(_Ob, __VA_ARGS__)
# define ULIB_SERIALIZE_OBJECT(_Ob,...) _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_OBJECT(_Ob,__VA_ARGS__) #define ULIB_SERIALIZABLE_OBJECT(_Ob) \
# define ULIB_SERIALIZE_OBJECT_PROPS(_Ob) _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_PROPS(_Ob) _ULIB_DETAIL_UNINTRUSIVE_SERIALIZABLE_OBJECT(_Ob) \
# define AR(_name) _ULIB_DETAIL_UNINTRUSIVE_AR_(_name) ULIB_CLASS_EXPORT_OBJECT_KEY(_Ob)
# define HR(_name) _ULIB_DETAIL_UNINTRUSIVE_AR_(_name) #define ULIB_SERIALIZE_OBJECT(_Ob, ...) \
_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_OBJECT(_Ob, __VA_ARGS__)
#define AR(_name) _ULIB_DETAIL_UNINTRUSIVE_AR_(_name)
#define HR(_name) _ULIB_DETAIL_UNINTRUSIVE_AR_(_name)
#endif #endif
#define ULIB_SERIALIZE_ACCESS \
friend class boost::serialization::access; \
template <class T> friend class boost::serialization::access2;
#define ULIB_SERIALIZE_ACCESS \ #define ULIB_CLASS_EXPORT_KEY(_FullNamespaceClass) \
friend class boost::serialization::access; \ BOOST_CLASS_EXPORT_KEY(_FullNamespaceClass)
template <class T> friend class boost::serialization::access2;
#define ULIB_CLASS_EXPORT_KEY(_FullNamespaceClass) \ #define ULIB_CLASS_EXPORT_OBJECT_KEY(_FullNamespaceClass) \
BOOST_CLASS_EXPORT_KEY(_FullNamespaceClass) BOOST_CLASS_EXPORT_KEY(_FullNamespaceClass)
#define ULIB_CLASS_EXPORT_OBJECT_KEY(_FullNamespaceClass) \
BOOST_CLASS_EXPORT_KEY(_FullNamespaceClass) \
BOOST_CLASS_EXPORT_KEY(_FullNamespaceClass::ObjectProps) \
BOOST_CLASS_EXPORT_KEY(uLib::ObjectPropsImpl<_FullNamespaceClass>)
#define _SERIALIZE_IMPL_SEQ \
(uLib::Archive::text_iarchive) \
(uLib::Archive::text_oarchive) \
(uLib::Archive::hrt_iarchive) \
(uLib::Archive::hrt_oarchive) \
(uLib::Archive::xml_iarchive) \
(uLib::Archive::xml_oarchive) \
(uLib::Archive::log_archive)
#define _SERIALIZE_IMPL_SEQ \
(uLib::Archive::text_iarchive)(uLib::Archive::text_oarchive)( \
uLib::Archive:: \
hrt_iarchive)(uLib::Archive:: \
hrt_oarchive)(uLib::Archive:: \
xml_iarchive)(uLib::Archive:: \
xml_oarchive)(uLib::Archive:: \
log_archive)
/** Solving virtual class check problem */ /** Solving virtual class check problem */
#define _ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE(_Base,_Derived) namespace boost{ template<> struct is_virtual_base_of<_Base,_Derived>: public boost::mpl::true_ {}; } #define _ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE(_Base, _Derived) \
#define _ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE_OP(r,data,elem) _ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE(elem,data) namespace boost { \
template <> \
struct is_virtual_base_of<_Base, _Derived> : public boost::mpl::true_ {}; \
}
#define _ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE_OP(r, data, elem) \
_ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE(elem, data)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -220,38 +195,57 @@ namespace uLib {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// INTRUSIVE SERIALIZATION ( NOT WORKING YET !! ) // // INTRUSIVE SERIALIZATION ( NOT WORKING YET !! ) //
#define _ULIB_DETAIL_INTRUSIVE_AR_(name) ar & BOOST_SERIALIZATION_NVP(name); #define _ULIB_DETAIL_INTRUSIVE_AR_(name) ar &BOOST_SERIALIZATION_NVP(name);
#define _ULIB_DETAIL_INTRUSIVE_SERIALIZE_FUNC(Class,Archive) \ #define _ULIB_DETAIL_INTRUSIVE_SERIALIZE_FUNC(Class, Archive) \
template void Class::serialize(Archive &ar,const unsigned int); template void Class::serialize(Archive &ar, const unsigned int);
#define _ULIB_DETAIL_INTRUSIVE_SERIALIZE_FUNC_OP(r,data,elem) _ULIB_DETAIL_INTRUSIVE_SERIALIZE_FUNC(data,elem); #define _ULIB_DETAIL_INTRUSIVE_SERIALIZE_FUNC_OP(r, data, elem) \
_ULIB_DETAIL_INTRUSIVE_SERIALIZE_FUNC(data, elem);
#define _ULIB_DETAIL_INTRUSIVE_SERIALIZABLE_OBJECT \
typedef boost::mpl::bool_<true> serializable; \
typedef boost::mpl::remove_if< TypeList, IsUnSerializable >::type SerilizableTypeList; \
void PrintSerializableListId() { boost::mpl::for_each<SerilizableTypeList>(PrintTypeId()); } \
template <class ArchiveT> void serialize(ArchiveT &ar,const unsigned int version); \
template <class ArchiveT> void serialize_parents(ArchiveT &ar,const unsigned int version); \
template <class ArchiveT> void save_override(ArchiveT &ar,const unsigned int version);
#define _ULIB_DETAIL_INTRUSIVE_SERIALIZE_OBJECT(_Ob,...) \
template <class ArchiveT> void _Ob::serialize(ArchiveT &ar, const unsigned int version) { \
boost::serialization::void_cast_register<_Ob,_Ob::BaseClass>(static_cast<_Ob *>(NULL),static_cast<_Ob::BaseClass *>(NULL)); \
_Ob::serialize_parents(ar,version); \
_Ob::save_override(ar,version); }\
template <class ArchiveT> void _Ob::serialize_parents(ArchiveT &ar, const unsigned int v) { \
BOOST_PP_SEQ_FOR_EACH(_AR_OP,ar,BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))); } \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_INTRUSIVE_SERIALIZE_FUNC_OP,_Ob,_SERIALIZE_IMPL_SEQ)\
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE_OP,_Ob,BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \
ULIB_CLASS_EXPORT_IMPLEMENT(_Ob) \
namespace boost { \
namespace serialization { \
template<class ArchiveT> inline void load_construct_data(ArchiveT & ar, _Ob *o, const unsigned int file_version) \
{ ::new(o)_Ob(); o->init_parameters(); } }}\
template <class ArchiveT> void _Ob::save_override(ArchiveT &ar, const unsigned int version)
#define _ULIB_DETAIL_INTRUSIVE_SERIALIZABLE_OBJECT \
typedef boost::mpl::bool_<true> serializable; \
typedef boost::mpl::remove_if<TypeList, IsUnSerializable>::type \
SerilizableTypeList; \
void PrintSerializableListId() { \
boost::mpl::for_each<SerilizableTypeList>(PrintTypeId()); \
} \
template <class ArchiveT> \
void serialize(ArchiveT &ar, const unsigned int version); \
template <class ArchiveT> \
void serialize_parents(ArchiveT &ar, const unsigned int version); \
template <class ArchiveT> \
void save_override(ArchiveT &ar, const unsigned int version);
#define _ULIB_DETAIL_INTRUSIVE_SERIALIZE_OBJECT(_Ob, ...) \
template <class ArchiveT> \
void _Ob::serialize(ArchiveT &ar, const unsigned int version) { \
boost::serialization::void_cast_register<_Ob, _Ob::BaseClass>( \
static_cast<_Ob *>(NULL), static_cast<_Ob::BaseClass *>(NULL)); \
_Ob::serialize_parents(ar, version); \
_Ob::save_override(ar, version); \
} \
template <class ArchiveT> \
void _Ob::serialize_parents(ArchiveT &ar, const unsigned int v) { \
BOOST_PP_SEQ_FOR_EACH(_AR_OP, ar, BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))); \
} \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_INTRUSIVE_SERIALIZE_FUNC_OP, _Ob, \
_SERIALIZE_IMPL_SEQ) \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE_OP, _Ob, \
BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \
ULIB_CLASS_EXPORT_IMPLEMENT(_Ob) \
namespace boost { \
namespace serialization { \
template <class ArchiveT> \
inline void load_construct_data(ArchiveT &ar, _Ob *o, \
const unsigned int file_version) { \
::new (o) _Ob(); \
o->init_parameters(); \
} \
} \
} \
template <class ArchiveT> \
void _Ob::save_override(ArchiveT &ar, const unsigned int version)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -261,152 +255,171 @@ namespace uLib {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// UNINTRUSIVE SERIALIZATION // UNINTRUSIVE SERIALIZATION
#define _UNAR_OP(r,data,elem) ar&boost::serialization::make_nvp(BOOST_PP_STRINGIZE(elem),boost::serialization::base_object<elem>(ob)); #define _UNAR_OP(r, data, elem) \
ar &boost::serialization::make_nvp( \
BOOST_PP_STRINGIZE(elem), boost::serialization::base_object<elem>(ob));
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC(Class,Archive) \ #define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC(Class, Archive) \
template void boost::serialization::serialize(Archive &ar, Class &ob, const unsigned int i); template void boost::serialization::serialize(Archive &ar, Class &ob, \
const unsigned int i);
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP(r,data,elem) _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC(data,elem)
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP(r, data, elem) \
_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC(data, elem)
// NOTE: becouse of BOOST_PP_VARIADIC_SIZE issue of some boost macro has two // NOTE: becouse of BOOST_PP_VARIADIC_SIZE issue of some boost macro has two
// different implementation // different implementation
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZABLE(_Ob) \ #define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZABLE(_Ob) \
namespace boost { namespace serialization { \ namespace boost { \
template <class ArchiveT> void serialize (ArchiveT &ar, _Ob &ob, const unsigned int version); \ namespace serialization { \
template <class ArchiveT> void serialize_parents (ArchiveT &ar, _Ob &ob, const unsigned int version); \ template <class ArchiveT> \
template <> struct access2< _Ob > { template <class ArchiveT> static void save_override (ArchiveT &ar, _Ob &ob, const unsigned int version); }; }} void serialize(ArchiveT &ar, _Ob &ob, const unsigned int version); \
template <class ArchiveT> \
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE(_Ob) \ void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int version); \
namespace boost { namespace serialization { \ template <> struct access2<_Ob> { \
template <class ArchiveT> void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int v) {} \ template <class ArchiveT> \
template <class ArchiveT> void serialize (ArchiveT &ar, _Ob &ob, const unsigned int version) { \ static void save_override(ArchiveT &ar, _Ob &ob, \
serialize_parents(ar,ob,version); \ const unsigned int version); \
access2< _Ob >::save_override(ar,ob,version); } }}\ }; \
ULIB_CLASS_EXPORT_IMPLEMENT(_Ob) \ } \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP,_Ob,_SERIALIZE_IMPL_SEQ)\ }
template <class ArchiveT> void boost::serialization::access2< _Ob >::save_override(ArchiveT &ar, _Ob &ob, const unsigned int version)
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_DERIVED(_Ob,...) \
namespace boost { namespace serialization { \
template <class ArchiveT> void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int v) { \
BOOST_PP_IF(BOOST_PP_VARIADIC_SIZE((__VA_ARGS__)),BOOST_PP_SEQ_FOR_EACH(_UNAR_OP,ob,BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__)));,) } \
template <class ArchiveT> void serialize (ArchiveT &ar, _Ob &ob, const unsigned int version) { \
serialize_parents(ar,ob,version); \
access2< _Ob >::save_override (ar,ob,version); } }}\
ULIB_CLASS_EXPORT_IMPLEMENT(_Ob) \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP,_Ob,_SERIALIZE_IMPL_SEQ) \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE_OP,_Ob,BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \
template <class ArchiveT> void boost::serialization::access2< _Ob >::save_override(ArchiveT &ar, _Ob &ob, const unsigned int version)
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZABLE_OBJECT(_Ob) \
namespace boost { namespace serialization { \
template <class ArchiveT> void serialize (ArchiveT &ar, _Ob &ob, const unsigned int version); \
template <class ArchiveT> void serialize_parents (ArchiveT &ar, _Ob &ob, const unsigned int version); \
template <> struct access2< _Ob > { template <class ArchiveT> static void save_override (ArchiveT &ar, _Ob &ob, const unsigned int version); }; \
template <class ArchiveT> void serialize (ArchiveT &ar, class _Ob::ObjectProps &ob, const unsigned int version); \
template <class ArchiveT> void save_override (ArchiveT &ar, class _Ob::ObjectProps &ob, const unsigned int version); }}
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_OBJECT(_Ob,...) \
namespace boost { namespace serialization { \
template <class ArchiveT> void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int v) { \
/* PP serialize */ BOOST_PP_SEQ_FOR_EACH(_UNAR_OP,ob,BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))); \
/* MPL serialize */ /*uLib::mpl::for_each<_Ob::BaseList>(uLib::detail::Serializable::serialize_baseobject<_Ob,ArchiveT>(ob,ar) );*/ } \
template<class ArchiveT> inline void load_construct_data(ArchiveT & ar, _Ob *ob, const unsigned int file_version) { \
::new(ob)_Ob(); uLib::detail::ObjectProps::initializer::init_object(ob); } \
template <class ArchiveT> void serialize (ArchiveT &ar, _Ob &ob, const unsigned int version) { \
void_cast_register<_Ob,_Ob::BaseClass>(static_cast<_Ob *>(NULL),static_cast<_Ob::BaseClass *>(NULL)); /*fix*/ \
serialize_parents(ar,ob,version); \
access2< _Ob >::save_override (ar,ob,version); } }}\
ULIB_CLASS_EXPORT_IMPLEMENT(_Ob) \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE_OP,_Ob,BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP,_Ob,_SERIALIZE_IMPL_SEQ)\
template <class ArchiveT> void boost::serialization::access2< _Ob >::save_override(ArchiveT &ar, _Ob &ob, const unsigned int version)
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_PROPS(_Ob) \
namespace boost { namespace serialization { \
template <class ArchiveT> void serialize (ArchiveT &ar, _Ob::ObjectProps &ob, const unsigned int version) { \
save_override (ar,ob,version); } }}\
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP,_Ob::ObjectProps,_SERIALIZE_IMPL_SEQ)\
ULIB_CLASS_EXPORT_IMPLEMENT(_Ob::ObjectProps) \
ULIB_CLASS_EXPORT_IMPLEMENT(uLib::ObjectPropsImpl<_Ob>) \
template <class ArchiveT> void boost::serialization::save_override(ArchiveT &ar, _Ob::ObjectProps &ob, const unsigned int version)
#define _ULIB_DETAIL_UNINTRUSIVE_AR_(name) boost::serialization::make_nvp(BOOST_PP_STRINGIZE(name),ob.name)
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE(_Ob) \
namespace boost { \
namespace serialization { \
template <class ArchiveT> \
void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int v) {} \
template <class ArchiveT> \
void serialize(ArchiveT &ar, _Ob &ob, const unsigned int version) { \
serialize_parents(ar, ob, version); \
access2<_Ob>::save_override(ar, ob, version); \
} \
} \
} \
ULIB_CLASS_EXPORT_IMPLEMENT(_Ob) \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP, _Ob, \
_SERIALIZE_IMPL_SEQ) \
template <class ArchiveT> \
void boost::serialization::access2<_Ob>::save_override( \
ArchiveT &ar, _Ob &ob, const unsigned int version)
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_DERIVED(_Ob, ...) \
namespace boost { \
namespace serialization { \
template <class ArchiveT> \
void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int v) { \
BOOST_PP_IF(BOOST_PP_VARIADIC_SIZE((__VA_ARGS__)), \
BOOST_PP_SEQ_FOR_EACH(_UNAR_OP, ob, \
BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))); \
, ) \
} \
template <class ArchiveT> \
void serialize(ArchiveT &ar, _Ob &ob, const unsigned int version) { \
serialize_parents(ar, ob, version); \
access2<_Ob>::save_override(ar, ob, version); \
} \
} \
} \
ULIB_CLASS_EXPORT_IMPLEMENT(_Ob) \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP, _Ob, \
_SERIALIZE_IMPL_SEQ) \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE_OP, _Ob, \
BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \
template <class ArchiveT> \
void boost::serialization::access2<_Ob>::save_override( \
ArchiveT &ar, _Ob &ob, const unsigned int version)
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZABLE_OBJECT(_Ob) \
namespace boost { \
namespace serialization { \
template <class ArchiveT> \
void serialize(ArchiveT &ar, _Ob &ob, const unsigned int version); \
template <class ArchiveT> \
void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int version); \
template <> struct access2<_Ob> { \
template <class ArchiveT> \
static void save_override(ArchiveT &ar, _Ob &ob, \
const unsigned int version); \
}; \
} \
}
#define _ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_OBJECT(_Ob, ...) \
namespace boost { \
namespace serialization { \
template <class ArchiveT> \
void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int v) { \
/* PP serialize */ BOOST_PP_SEQ_FOR_EACH( \
_UNAR_OP, ob, BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))); \
/* MPL serialize */ /*uLib::mpl::for_each<_Ob::BaseList>(uLib::detail::Serializable::serialize_baseobject<_Ob,ArchiveT>(ob,ar) );*/ } \
template <class ArchiveT> \
inline void load_construct_data(ArchiveT &ar, _Ob *ob, \
const unsigned int file_version) { \
::new (ob) _Ob(); \
} \
template <class ArchiveT> \
void serialize(ArchiveT &ar, _Ob &ob, const unsigned int version) { \
void_cast_register<_Ob, _Ob::BaseClass>( \
static_cast<_Ob *>(NULL), \
static_cast<_Ob::BaseClass *>(NULL)); /*fix*/ \
serialize_parents(ar, ob, version); \
access2<_Ob>::save_override(ar, ob, version); \
} \
} \
} \
ULIB_CLASS_EXPORT_IMPLEMENT(_Ob) \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE_OP, _Ob, \
BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \
BOOST_PP_SEQ_FOR_EACH(_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_FUNC_OP, _Ob, \
_SERIALIZE_IMPL_SEQ) \
template <class ArchiveT> \
void boost::serialization::access2<_Ob>::save_override( \
ArchiveT &ar, _Ob &ob, const unsigned int version)
#define _ULIB_DETAIL_UNINTRUSIVE_AR_(name) \
boost::serialization::make_nvp(BOOST_PP_STRINGIZE(name), ob.name)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace detail { namespace detail {
struct Serializable { struct Serializable {
/** /**
* Serializable trait to check if an object type is serializable. * Serializable trait to check if an object type is serializable.
* This only works if UNINTRUSIVE SERIALIZATION is applyed; in intrusive * This only works if UNINTRUSIVE SERIALIZATION is applyed; in intrusive
* cases a has_serialize trait should be implemented * cases a has_serialize trait should be implemented
*/ */
template <class T> template <class T> struct serializable_trait : mpl::bool_<false> {};
struct serializable_trait : mpl::bool_<false> {};
/**
* IsA Serializable Implementation Template
*/
template <class T>
struct IsA : serializable_trait<T> {};
template <class ThisClass, class Archive>
struct serialize_baseobject {
ThisClass & m_object;
Archive & m_ar;
serialize_baseobject(ThisClass &o, Archive &ar) : m_object(o), m_ar(ar) {}
template <class T> void operator()(T &o) {
m_ar & boost::serialization::make_nvp(
typeid(T).name() ,
boost::serialization::base_object<T>(m_object));
}
};
/**
* IsA Serializable Implementation Template
*/
template <class T> struct IsA : serializable_trait<T> {};
template <class ThisClass, class Archive> struct serialize_baseobject {
ThisClass &m_object;
Archive &m_ar;
serialize_baseobject(ThisClass &o, Archive &ar) : m_object(o), m_ar(ar) {}
template <class T> void operator()(T &o) {
m_ar &boost::serialization::make_nvp(
typeid(T).name(), boost::serialization::base_object<T>(m_object));
}
};
}; };
} // namespace detail
} // detail
struct Serializable { struct Serializable {
friend class boost::serialization::access; friend class boost::serialization::access;
template <class T> friend class boost::serialization::access2; template <class T> friend class boost::serialization::access2;
virtual ~Serializable() {} virtual ~Serializable() {}
protected: protected:
}; };
} // namespace uLib
} // uLib
#endif // U_SERIALIZABLE_H #endif // U_SERIALIZABLE_H

View File

@@ -23,21 +23,19 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef U_CORE_SIGNAL_H #ifndef U_CORE_SIGNAL_H
#define U_CORE_SIGNAL_H #define U_CORE_SIGNAL_H
#include <boost/typeof/typeof.hpp> #include <boost/typeof/typeof.hpp>
#include <boost/signals2/signal.hpp> #include <boost/signals2/signal.hpp>
#include <boost/signals2/slot.hpp>
#include <boost/signals2/signal_type.hpp> #include <boost/signals2/signal_type.hpp>
#include <boost/signals2/slot.hpp>
#include "Function.h" #include "Function.h"
#include <boost/bind/bind.hpp>
using namespace boost::placeholders;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -48,12 +46,15 @@
#define slots #define slots
#define signals /*virtual void init_signals();*/ public #define signals /*virtual void init_signals();*/ public
#define emit #define emit
#define SLOT(a) BOOST_STRINGIZE(a) #define SLOT(a) BOOST_STRINGIZE(a)
#define SIGNAL(a) BOOST_STRINGIZE(a) #define SIGNAL(a) BOOST_STRINGIZE(a)
#define _ULIB_DETAIL_SIGNAL_EMIT(_name,...) \ #define _ULIB_DETAIL_SIGNAL_EMIT(_name, ...) \
static BOOST_AUTO(sig,this->findOrAddSignal(&_name)); \ do { \
sig->operator()(__VA_ARGS__); BOOST_AUTO(sig, this->findOrAddSignal(&_name)); \
if (sig) \
sig->operator()(__VA_ARGS__); \
} while (0)
/** /**
* Utility macro to implement signal emission implementa una delle seguenti: * Utility macro to implement signal emission implementa una delle seguenti:
@@ -66,103 +67,101 @@
* // cast automatico // * // cast automatico //
* static BOOST_AUTO(sig,this->findOrAddSignal(&Ob1::V0)); * static BOOST_AUTO(sig,this->findOrAddSignal(&Ob1::V0));
* sig->operator()(); * sig->operator()();
*/ */
#define ULIB_SIGNAL_EMIT(_name,...) _ULIB_DETAIL_SIGNAL_EMIT(_name,__VA_ARGS__) #define ULIB_SIGNAL_EMIT(_name, ...) \
_ULIB_DETAIL_SIGNAL_EMIT(_name, __VA_ARGS__)
namespace uLib { namespace uLib {
// A boost::signal wrapper structure /////////////////////////////////////////// // A boost::signal wrapper structure ///////////////////////////////////////////
// TODO ... // TODO ...
typedef boost::signals2::signal_base SignalBase; typedef boost::signals2::signal_base SignalBase;
template <typename T> template <typename T> struct Signal {
struct Signal { typedef boost::signals2::signal<T> type;
typedef boost::signals2::signal<T> type;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace detail { namespace detail {
template <typename FuncT, typename SigSignature, int arity>
template <typename FuncT, int arity>
struct ConnectSignal {}; struct ConnectSignal {};
template <typename FuncT> template <typename FuncT, typename SigSignature>
struct ConnectSignal< FuncT, 0 > { struct ConnectSignal<FuncT, SigSignature, 0> {
static void connect(SignalBase *sigb, FuncT slof, typename FunctionPointer<FuncT>::Object *receiver) { static void connect(SignalBase *sigb, FuncT slof,
typedef typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type SigT; typename FunctionPointer<FuncT>::Object *receiver) {
reinterpret_cast<SigT*>(sigb)->connect(slof); typedef typename Signal<SigSignature>::type SigT;
} reinterpret_cast<SigT *>(sigb)->connect(slof);
}
}; };
template <typename FuncT> template <typename FuncT, typename SigSignature>
struct ConnectSignal< FuncT, 1 > { struct ConnectSignal<FuncT, SigSignature, 1> {
static void connect(SignalBase *sigb, FuncT slof, typename FunctionPointer<FuncT>::Object *receiver) { static void connect(SignalBase *sigb, FuncT slof,
typedef typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type SigT; typename FunctionPointer<FuncT>::Object *receiver) {
reinterpret_cast<SigT*>(sigb)->connect(boost::bind(slof,receiver)); typedef typename Signal<SigSignature>::type SigT;
} reinterpret_cast<SigT *>(sigb)->connect(boost::bind(slof, receiver));
}
}; };
template <typename FuncT> template <typename FuncT, typename SigSignature>
struct ConnectSignal< FuncT, 2 > { struct ConnectSignal<FuncT, SigSignature, 2> {
static void connect(SignalBase *sigb, FuncT slof, typename FunctionPointer<FuncT>::Object *receiver) { static void connect(SignalBase *sigb, FuncT slof,
typedef typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type SigT; typename FunctionPointer<FuncT>::Object *receiver) {
reinterpret_cast<SigT*>(sigb)->connect(boost::bind(slof,receiver,_1)); typedef typename Signal<SigSignature>::type SigT;
} reinterpret_cast<SigT *>(sigb)->connect(boost::bind(slof, receiver, _1));
}
}; };
template <typename FuncT> template <typename FuncT, typename SigSignature>
struct ConnectSignal< FuncT, 3 > { struct ConnectSignal<FuncT, SigSignature, 3> {
static void connect(SignalBase *sigb, FuncT slof, typename FunctionPointer<FuncT>::Object *receiver) { static void connect(SignalBase *sigb, FuncT slof,
typedef typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type SigT; typename FunctionPointer<FuncT>::Object *receiver) {
reinterpret_cast<SigT*>(sigb)->connect(boost::bind(slof,receiver,_1,_2)); typedef typename Signal<SigSignature>::type SigT;
} reinterpret_cast<SigT *>(sigb)->connect(
boost::bind(slof, receiver, _1, _2));
}
}; };
template <typename FuncT> template <typename FuncT, typename SigSignature>
struct ConnectSignal< FuncT, 4 > { struct ConnectSignal<FuncT, SigSignature, 4> {
static void connect(SignalBase *sigb, FuncT slof, typename FunctionPointer<FuncT>::Object *receiver) { static void connect(SignalBase *sigb, FuncT slof,
typedef typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type SigT; typename FunctionPointer<FuncT>::Object *receiver) {
reinterpret_cast<SigT*>(sigb)->connect(boost::bind(slof,receiver,_1,_2,_3)); typedef typename Signal<SigSignature>::type SigT;
} reinterpret_cast<SigT *>(sigb)->connect(
boost::bind(slof, receiver, _1, _2, _3));
}
}; };
template <typename FuncT> template <typename FuncT, typename SigSignature>
struct ConnectSignal< FuncT, 5 > { struct ConnectSignal<FuncT, SigSignature, 5> {
static void connect(SignalBase *sigb, FuncT slof, typename FunctionPointer<FuncT>::Object *receiver) { static void connect(SignalBase *sigb, FuncT slof,
typedef typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type SigT; typename FunctionPointer<FuncT>::Object *receiver) {
reinterpret_cast<SigT*>(sigb)->connect(boost::bind(slof,receiver,_1,_2,_3,_4)); typedef typename Signal<SigSignature>::type SigT;
} reinterpret_cast<SigT *>(sigb)->connect(
boost::bind(slof, receiver, _1, _2, _3, _4));
}
}; };
} // namespace detail
} // detail template <typename FuncT> SignalBase *NewSignal(FuncT f) {
return new
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type;
template <typename FuncT>
SignalBase *NewSignal(FuncT f) {
// seems to work wow !
return new Signal<void()>::type;
} }
template <typename FuncT> template <typename SigSignature, typename FuncT>
void ConnectSignal(SignalBase *sigb, FuncT slof, typename FunctionPointer<FuncT>::Object *receiver) void ConnectSignal(SignalBase *sigb, FuncT slof,
{ typename FunctionPointer<FuncT>::Object *receiver) {
detail::ConnectSignal< FuncT, FunctionPointer<FuncT>::arity >::connect(sigb,slof,receiver); detail::ConnectSignal<FuncT, SigSignature,
FunctionPointer<FuncT>::arity>::connect(sigb, slof,
receiver);
} }
} // namespace uLib
} // uLib
#endif // SIGNAL_H #endif // SIGNAL_H

View File

@@ -23,8 +23,6 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef U_CORE_TYPES_H #ifndef U_CORE_TYPES_H
#define U_CORE_TYPES_H #define U_CORE_TYPES_H
@@ -33,253 +31,182 @@
#include <boost/preprocessor.hpp> #include <boost/preprocessor.hpp>
//#include <ltk/ltktypes.h> // #include <ltk/ltktypes.h>
#include "Core/Macros.h" #include "Core/Macros.h"
#include "Core/Mpl.h" #include "Core/Mpl.h"
namespace uLib { namespace uLib {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace detail { namespace detail {
struct TypeIntrospection { struct TypeIntrospection {
// BOOST IMPL // // BOOST IMPL //
BOOST_MPL_HAS_XXX_TRAIT_DEF(type_info) BOOST_MPL_HAS_XXX_TRAIT_DEF(type_info)
// SFINAE IMPL // // SFINAE IMPL //
/* /*
template <typename T> template <typename T>
struct has_type_info { struct has_type_info {
typedef char yes[1]; typedef char yes[1];
typedef char no[2]; typedef char no[2];
template <typename U> static yes& test(typename U::type_info::BaseList*); template <typename U> static yes& test(typename U::type_info::BaseList*);
template <typename > static no& test(...); template <typename > static no& test(...);
// struct apply { // struct apply {
static const bool value = sizeof(test<T>(0)) == sizeof(yes); static const bool value = sizeof(test<T>(0)) == sizeof(yes);
typedef boost::mpl::bool_<value> type; typedef boost::mpl::bool_<value> type;
// }; // };
}; };
*/ */
/** IsA Introspectable Object Implementation Template */ /** IsA Introspectable Object Implementation Template */
template <class T> template <class T> struct IsIntrospectable : has_type_info<T> {};
struct IsIntrospectable : has_type_info<T> {};
template <typename T> struct access { template <typename T> struct access {
typedef typename T::type_info type_info; typedef typename T::type_info type_info;
};
template <typename T> struct child_first_impl {
template <class T1, bool cond> struct lambda_CFList_f {
typedef mpl::vector<T1> type;
}; };
template <typename T> template <class T1> struct lambda_CFList_f<T1, true> {
struct child_first_impl { // typedef typename T1::type_info::CFList type;
typedef typename access<T1>::type_info::CFList type;
template <class T1, bool cond>
struct lambda_CFList_f {
typedef mpl::vector<T1> type;
};
template <class T1>
struct lambda_CFList_f<T1,true> {
// typedef typename T1::type_info::CFList type;
typedef typename access<T1>::type_info::CFList type;
};
template <class T1>
struct lambda_CFList : lambda_CFList_f<T1, has_type_info<T1>::value> {};
/** Transforms all Base Type into proper CFList */
typedef typename mpl::transform_view < typename access<T>::type_info::BaseList
, lambda_CFList<mpl::_>
>::type CFListSeq;
/** Folds each CFList into a new sequence */
typedef typename mpl::fold< CFListSeq
, mpl::vector<>
, mpl::copy< mpl::_1
, mpl::back_inserter<mpl::_2>
>
>::type Childs;
/** Add This Class to final CFList sequence */
typedef typename mpl::copy< Childs
, mpl::back_inserter< mpl::vector<T> >
>::type type;
}; };
template <class T1>
struct lambda_CFList : lambda_CFList_f<T1, has_type_info<T1>::value> {};
/** /** Transforms all Base Type into proper CFList */
* Tests if T has a member called type_info then compile type CFList typedef
*/ typename mpl::transform_view<typename access<T>::type_info::BaseList,
template <typename T> lambda_CFList<mpl::_>>::type CFListSeq;
struct child_first : mpl::if_< has_type_info<T>
, child_first_impl<T>
, mpl::vector<>
>::type {};
/** Folds each CFList into a new sequence */
typedef typename mpl::fold<
CFListSeq, mpl::vector<>,
mpl::copy<mpl::_1, mpl::back_inserter<mpl::_2>>>::type Childs;
/** Add This Class to final CFList sequence */
typedef typename mpl::copy<Childs, mpl::back_inserter<mpl::vector<T>>>::type
type;
};
/**
* Tests if T has a member called type_info then compile type CFList
*/
template <typename T>
struct child_first
: mpl::if_<has_type_info<T>, child_first_impl<T>, mpl::vector<>>::type {};
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// TYPE ADAPTERS // FINIRE !!! // TYPE ADAPTERS // FINIRE !!!
//#define _REPETITION_V(vz,vn,vdata) // #define _REPETITION_V(vz,vn,vdata)
//template < class TypeList >
//class TypeAdapterInputInterface {
// virtual ~TypeAdapterInputInterface() {}
//public:
// template < class TypeList >
// class TypeAdapterInputInterface {
// virtual ~TypeAdapterInputInterface() {}
// public:
// virtual void operator()(int val) {} // virtual void operator()(int val) {}
// virtual void operator()(std::string val) {} // virtual void operator()(std::string val) {}
//}; //};
} // namespace detail
} // detail ////////////////////////////////////////////////////////////////////
#define CONSTEXPR BOOST_CONSTEXPR #define CONSTEXPR BOOST_CONSTEXPR
// typedef ltk::Real_t Real_t;
//typedef ltk::Real_t Real_t;
#ifndef LTK_DOUBLE_PRECISION #ifndef LTK_DOUBLE_PRECISION
typedef float Real_t; typedef float Real_t;
#else #else
typedef double Real_t; typedef double Real_t;
#endif #endif
//typedef ltk::Id_t Id_t; // typedef ltk::Id_t Id_t;
typedef id_t Id_t; typedef id_t Id_t;
////typedef ltk::Size_t Size_t; ////typedef ltk::Size_t Size_t;
//typedef ltk::Pointer_t Pointer_t; // typedef ltk::Pointer_t Pointer_t;
typedef void * Pointer_t; typedef void *Pointer_t;
typedef bool Bool_t; //Boolean (0=false, 1=true) (bool) typedef bool Bool_t; // Boolean (0=false, 1=true) (bool)
//--- bit manipulation --------------------------------------------------------- //--- bit manipulation ---------------------------------------------------------
#ifndef BIT #ifndef BIT
#define BIT(n) (1ULL << (n)) #define BIT(n) (1ULL << (n))
#endif #endif
#ifndef SETBIT #ifndef SETBIT
#define SETBIT(n,i) ((n) |= BIT(i)) #define SETBIT(n, i) ((n) |= BIT(i))
#endif #endif
#ifndef CLRBIT #ifndef CLRBIT
#define CLRBIT(n,i) ((n) &= ~BIT(i)) #define CLRBIT(n, i) ((n) &= ~BIT(i))
#endif #endif
#ifndef TESTBIT #ifndef TESTBIT
#define TESTBIT(n,i) ((Bool_t)(((n) & BIT(i)) != 0)) #define TESTBIT(n, i) ((Bool_t)(((n) & BIT(i)) != 0))
#endif #endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// TYPE INTROSPECTION FOR OBJECTS // // TYPE INTROSPECTION FOR OBJECTS //
#define uLibTypeMacro(thisClass, ...) \
\
#define uLibTypeMacro(thisClass,...) \ /* Friendship detail for accessing introspection */ \
\ template <typename> friend class uLib::detail::TypeIntrospection::access; \
/* Friendship detail for accessing introspection */ \ \
template <typename> friend class uLib::detail::TypeIntrospection::access; \ /* type info structure*/ public: \
\ /* in GCC 4.8 must be public or dynamic_cast wont work */ \
/* type info structure*/ public: \ struct type_info { \
/* in GCC 4.8 must be public or dynamic_cast wont work */ \ /*WARNING: -std=c++0x required for this! */ \
struct type_info { \ constexpr static const char *name = BOOST_PP_STRINGIZE(thisClass); \
/*WARNING: -std=c++0x required for this! */ \ typedef BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__) BaseClass; \
constexpr static const char *name = BOOST_PP_STRINGIZE(thisClass); \ typedef thisClass ThisClass; \
typedef BOOST_PP_VARIADIC_ELEM(0,__VA_ARGS__) BaseClass; \ typedef uLib::mpl::vector<__VA_ARGS__, thisClass> TypeList; \
typedef thisClass ThisClass; \ typedef uLib::mpl::vector<__VA_ARGS__> BaseList; \
typedef uLib::mpl::vector<__VA_ARGS__,thisClass> TypeList; \ typedef uLib::detail::TypeIntrospection::child_first<ThisClass>::type \
typedef uLib::mpl::vector<__VA_ARGS__> BaseList; \ CFList; \
typedef uLib::detail::TypeIntrospection::child_first<ThisClass>::type CFList; \ }; \
}; \ \
\ public: \
public: \ typedef type_info::BaseClass BaseClass; \
typedef type_info::BaseClass BaseClass; \ virtual const char *type_name() const { return type_info::name; } \
virtual const char *type_name() const { return type_info::name; } \ /**/
/* Object Props fwd declaration*/ \
struct ObjectProps; \
/**/
/** /**
* TypeList inheritance introspection * TypeList inheritance introspection
*/ */
struct TypeIntrospection { struct TypeIntrospection {
template <typename T> template <typename T>
struct child_first : detail::TypeIntrospection::child_first<T> {}; struct child_first : detail::TypeIntrospection::child_first<T> {};
}; };
// SISTEMARE // // SISTEMARE //
struct PrintTypeId { struct PrintTypeId {
template <class T> template <class T> void operator()(T) const {
void operator()(T) const std::cout << typeid(T).name() << std::endl;
{ std::cout << typeid(T).name() << std::endl; } }
template <typename SeqT> template <typename SeqT> static void PrintMplSeq(SeqT *p = NULL) {
static void PrintMplSeq(SeqT *p = NULL) { boost::mpl::for_each<SeqT>(PrintTypeId()); } boost::mpl::for_each<SeqT>(PrintTypeId());
}
template <typename Class> template <typename Class> static void PrintType(Class *p = NULL) {
static void PrintType(Class *p = NULL) { std::cout << typeid(Class).name() << std::endl; } std::cout << typeid(Class).name() << std::endl;
}
}; };
} // namespace uLib
} // uLib
#endif // U_CORE_TYPES_H #endif // U_CORE_TYPES_H

View File

@@ -23,69 +23,49 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef U_CORE_UUID_H #ifndef U_CORE_UUID_H
#define U_CORE_UUID_H #define U_CORE_UUID_H
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/name_generator.hpp> #include <boost/uuid/name_generator.hpp>
#include <boost/uuid/random_generator.hpp> #include <boost/uuid/random_generator.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp> #include <boost/uuid/uuid_io.hpp>
#include "Core/Mpl.h" #include "Core/Mpl.h"
#include "Core/Object.h" #include "Core/Object.h"
namespace uLib { namespace uLib {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Object Registration // // Object Registration //
typedef boost::uuids::uuid uuid_t; typedef boost::uuids::uuid uuid_t;
extern uuid_t uLib_dns_uuid; extern uuid_t uLib_dns_uuid;
template < typename T > template <typename T> class type_id : public boost::uuids::uuid {
class type_id : public boost::uuids::uuid {
public: public:
type_id() : type_id()
m_size(sizeof(T)), : m_size(sizeof(T)),
uuid(boost::uuids::name_generator(uLib_dns_uuid)(typeid(T).name())) uuid(boost::uuids::name_generator(uLib_dns_uuid)(typeid(T).name())) {
{ std::cout << "Request for register new type\n"
std::cout << "Request for register new type\n" << << "name: " << typeid(T).name() << "\n"
"name: " << typeid(T).name() << "\n" << << "uuid: " << to_string(*this) << "\n";
"uuid: " << to_string(*this) << "\n"; }
}
explicit type_id(boost::uuids::uuid const& u) explicit type_id(boost::uuids::uuid const &u) : boost::uuids::uuid(u) {}
: boost::uuids::uuid(u) {}
operator boost::uuids::uuid() { unsigned int size() const { return m_size; }
return static_cast<boost::uuids::uuid&>(*this);
}
operator boost::uuids::uuid() const {
return static_cast<boost::uuids::uuid const&>(*this);
}
unsigned int size() const { return m_size; }
private: private:
unsigned int m_size; unsigned int m_size;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -94,70 +74,57 @@ private:
namespace detail { namespace detail {
class TypeRegister { class TypeRegister {
typedef boost::uuids::name_generator IDGen_t; typedef boost::uuids::name_generator IDGen_t;
public: public:
struct RegisterEntry { struct RegisterEntry {
uuid_t id; uuid_t id;
int size; int size;
}; };
TypeRegister(uuid_t const &dns) : TypeRegister(uuid_t const &dns) : gen(dns) {}
gen(dns) {}
template< typename T >
RegisterEntry * AddType(T *t = NULL) {
RegisterEntry en = { gen(typeid(T).name()), sizeof(T) };
for(int i=0; i < m_registry.size(); ++i)
if(en.id == m_registry[i].id) return &(m_registry[i]);
m_registry.push_back(en);
return &m_registry.back();
}
void PrintSelf(std::ostream &o) {
std::cout << "RegisterController: \n";
for (int i=0; i<m_registry.size(); ++i)
o << "type [" << i << "]: "
<< to_string(m_registry[i].id) << " "
<< m_registry[i].size << "\n";
o << "\n";
}
template <typename T> RegisterEntry *AddType(T *t = NULL) {
RegisterEntry en = {gen(typeid(T).name()), sizeof(T)};
for (int i = 0; i < m_registry.size(); ++i)
if (en.id == m_registry[i].id)
return &(m_registry[i]);
m_registry.push_back(en);
return &m_registry.back();
}
void PrintSelf(std::ostream &o) {
std::cout << "RegisterController: \n";
for (int i = 0; i < m_registry.size(); ++i)
o << "type [" << i << "]: " << to_string(m_registry[i].id) << " "
<< m_registry[i].size << "\n";
o << "\n";
}
private: private:
IDGen_t gen; IDGen_t gen;
std::vector<RegisterEntry> m_registry; std::vector<RegisterEntry> m_registry;
}; };
} // detail } // namespace detail
class TypeRegister : public detail::TypeRegister { class TypeRegister : public detail::TypeRegister {
public: public:
typedef detail::TypeRegister BaseClass; typedef detail::TypeRegister BaseClass;
typedef detail::TypeRegister::RegisterEntry Entry; typedef detail::TypeRegister::RegisterEntry Entry;
static TypeRegister* Controller(); static TypeRegister *Controller();
private: private:
TypeRegister(); // Blocks constructor TypeRegister(); // Blocks constructor
static TypeRegister *s_Instance; // Singleton instance static TypeRegister *s_Instance; // Singleton instance
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// OBJECT REGISTER // // OBJECT REGISTER //
} // namespace uLib
} // uLib
#endif // UUID_H #endif // UUID_H

View File

@@ -23,156 +23,433 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef U_CORE_VECTOR_H #ifndef U_CORE_VECTOR_H
#define U_CORE_VECTOR_H #define U_CORE_VECTOR_H
#include <vector>
#include <iostream> #include <iostream>
#include <map>
#include <mutex>
#include <vector>
#include <Core/DataAllocator.h>
#include <Core/StaticInterface.h>
#include <Core/SmartPointer.h>
#include <Core/CommaInitializer.h> #include <Core/CommaInitializer.h>
#include <Core/SmartPointer.h>
#include <Core/StaticInterface.h>
#ifdef USE_CUDA
#include <thrust/device_ptr.h>
#include <thrust/device_vector.h>
#endif
namespace uLib { namespace uLib {
// Vector Implemetation ... wraps std::vector // MetaAllocator Implementation ...
template <typename T> template <typename T> class MetaAllocator {
class Vector : public std::vector<T, std::allocator<T> >
{
typedef std::vector< T,std::allocator<T> > BaseClass;
typedef std::allocator<T> Allocator;
public:
typedef T TypeData;
typedef __gnu_cxx::__normal_iterator<T*, BaseClass > Iterator;
typedef __gnu_cxx::__normal_iterator<const T*, BaseClass> ConstIterator;
typedef CommaInitializer< Vector<T> , T > VectorCommaInit;
Vector(unsigned int size) : BaseClass(size) {}
Vector(unsigned int size, T &value) : BaseClass(size,value) {}
Vector() : BaseClass(0) {}
inline VectorCommaInit operator <<(T scalar) {
return VectorCommaInit(this, scalar);
}
inline void PrintSelf(std::ostream &o);
void remove_element(unsigned int index) {
std::swap(this->at(index),this->back());
this->pop_back();
}
void remove_element(T &t) {
std::swap(t, this->back());
this->pop_back();
}
};
template<typename T>
void Vector<T>::PrintSelf(std::ostream &o)
{
o << " *** uLib Vector *** \n";
o << " n. of items = " << this->size() << "\n";
for(int i=0; i< this->size(); ++i)
o << (T)this->at(i) << " ";
o << "\n";
}
template <typename T>
std::ostream & operator << (std::ostream &o, const Vector<T> &v) {
for(int i=0; i< v.size(); ++i)
o << (T)v.at(i) << " ";
o << "\n";
return o;
}
template <typename T>
std::ofstream & operator << (std::ofstream &o, const Vector<T> &v) {
for(int i=0; i< v.size(); ++i)
o << (T)v.at(i) << " ";
return o;
}
template < typename T >
std::istream & operator >> (std::istream &is, Vector<T> &v) {
T value;
while( is >> value ) {
if(is.fail()) v.push_back(0);
else v.push_back( value );
}
return is;
}
// Smart pointer Vector Implementation //
template <typename T>
class SmartVector : public SmartPointer< Vector<T> > {
typedef SmartPointer< Vector<T> > Base;
public: public:
using value_type = T;
using pointer = T *;
using const_pointer = const T *;
using reference = T &;
using const_reference = const T &;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
SmartVector() : Base(new Vector<T>()) { } template <class U> struct rebind {
SmartVector( const SmartVector &copy) : Base(copy) { } using other = MetaAllocator<U>;
SmartVector(unsigned int size) : Base(new Vector<T>((int)size)) { } };
virtual ~SmartVector() {} MetaAllocator() noexcept = default;
T& operator[](int p) { template <class U>
return Base::get()->at(p); constexpr MetaAllocator(const MetaAllocator<U> &) noexcept {}
T *allocate(std::size_t n) {
if (n == 0)
return nullptr;
DataAllocator<T> *da = new DataAllocator<T>(n, false);
T *ptr = da->GetRAMData();
std::lock_guard<std::mutex> lock(GetMutex());
GetAllocationMap()[ptr] = da;
return ptr;
} }
void swap_elements(unsigned int first, unsigned int second) { void deallocate(T *p, std::size_t /*n*/) noexcept {
std::swap(Base::get()->at(first),Base::get()->at(second)); if (!p)
return;
std::lock_guard<std::mutex> lock(GetMutex());
auto &map = GetAllocationMap();
auto it = map.find(p);
if (it != map.end()) {
delete it->second;
map.erase(it);
}
}
static DataAllocator<T> *GetDataAllocator(T *p) {
if (!p)
return nullptr;
std::lock_guard<std::mutex> lock(GetMutex());
auto &map = GetAllocationMap();
auto it = map.find(p);
if (it != map.end()) {
return it->second;
}
return nullptr;
}
private:
static std::map<T *, DataAllocator<T> *> &GetAllocationMap() {
static std::map<T *, DataAllocator<T> *> allocMap;
return allocMap;
}
static std::mutex &GetMutex() {
static std::mutex mtx;
return mtx;
}
};
template <class T, class U>
bool operator==(const MetaAllocator<T> &, const MetaAllocator<U> &) {
return true;
}
template <class T, class U>
bool operator!=(const MetaAllocator<T> &, const MetaAllocator<U> &) {
return false;
}
// Vector Implemetation ... wraps std::vector
template <typename T> class Vector : public std::vector<T, MetaAllocator<T>> {
typedef std::vector<T, MetaAllocator<T>> BaseClass;
typedef MetaAllocator<T> Allocator;
public:
typedef T TypeData;
typedef __gnu_cxx::__normal_iterator<T *, BaseClass> Iterator;
typedef __gnu_cxx::__normal_iterator<const T *, BaseClass> ConstIterator;
typedef CommaInitializer<Vector<T>, T> VectorCommaInit;
typedef typename BaseClass::iterator iterator;
typedef typename BaseClass::const_iterator const_iterator;
typedef typename BaseClass::size_type size_type;
typedef typename BaseClass::reference reference;
Vector(unsigned int size) : BaseClass(size) {}
Vector(unsigned int size, T &value) : BaseClass(size, value) {}
Vector() : BaseClass(0) {}
Vector(std::initializer_list<T> init) : BaseClass(init) {}
inline VectorCommaInit operator<<(T scalar) {
return VectorCommaInit(this, scalar);
}
void MoveToVRAM() {
if (auto alloc = MetaAllocator<T>::GetDataAllocator(BaseClass::data())) {
alloc->MoveToVRAM();
}
}
void MoveToRAM() {
if (auto alloc = MetaAllocator<T>::GetDataAllocator(BaseClass::data())) {
alloc->MoveToRAM();
}
}
T *GetVRAMData() {
if (auto alloc = MetaAllocator<T>::GetDataAllocator(BaseClass::data())) {
return alloc->GetVRAMData();
}
return nullptr;
}
const T *GetVRAMData() const {
if (auto alloc = MetaAllocator<T>::GetDataAllocator(
const_cast<T *>(BaseClass::data()))) {
return alloc->GetVRAMData();
}
return nullptr;
}
#ifdef USE_CUDA
/// Returns a thrust::device_ptr to the VRAM data (valid after MoveToVRAM()).
/// thrust::device_ptr<T> is itself a random-access iterator compatible with
/// all thrust algorithms (thrust::transform, thrust::sort,
/// thrust::for_each…).
thrust::device_ptr<T> DeviceData() {
if (auto alloc = MetaAllocator<T>::GetDataAllocator(BaseClass::data())) {
return thrust::device_pointer_cast(alloc->GetVRAMData());
}
return thrust::device_ptr<T>(nullptr);
}
thrust::device_ptr<const T> DeviceData() const {
if (auto alloc = MetaAllocator<T>::GetDataAllocator(
const_cast<T *>(BaseClass::data()))) {
return thrust::device_pointer_cast(
static_cast<const T *>(alloc->GetVRAMData()));
}
return thrust::device_ptr<const T>(nullptr);
}
/// Device-side begin iterator (valid after MoveToVRAM()).
thrust::device_ptr<T> DeviceBegin() { return DeviceData(); }
/// Device-side end iterator (valid after MoveToVRAM()).
thrust::device_ptr<T> DeviceEnd() {
return DeviceData() + static_cast<std::ptrdiff_t>(BaseClass::size());
}
thrust::device_ptr<const T> DeviceBegin() const { return DeviceData(); }
thrust::device_ptr<const T> DeviceEnd() const {
return DeviceData() + static_cast<std::ptrdiff_t>(BaseClass::size());
}
#endif // USE_CUDA
inline void PrintSelf(std::ostream &o);
// Overrides for auto-sync //
T &operator[](size_t i) {
this->MoveToRAM();
return BaseClass::operator[](i);
}
const T &operator[](size_t i) const {
const_cast<Vector *>(this)->MoveToRAM();
return BaseClass::operator[](i);
}
T &at(size_t i) {
this->MoveToRAM();
return BaseClass::at(i);
}
const T &at(size_t i) const {
const_cast<Vector *>(this)->MoveToRAM();
return BaseClass::at(i);
}
T &front() {
this->MoveToRAM();
return BaseClass::front();
}
const T &front() const {
const_cast<Vector *>(this)->MoveToRAM();
return BaseClass::front();
}
T &back() {
this->MoveToRAM();
return BaseClass::back();
}
const T &back() const {
const_cast<Vector *>(this)->MoveToRAM();
return BaseClass::back();
}
T *data() noexcept {
this->MoveToRAM();
return BaseClass::data();
}
const T *data() const noexcept {
const_cast<Vector *>(this)->MoveToRAM();
return BaseClass::data();
}
Iterator begin() noexcept {
this->MoveToRAM();
return BaseClass::begin();
}
ConstIterator begin() const noexcept {
const_cast<Vector *>(this)->MoveToRAM();
return BaseClass::begin();
}
Iterator end() noexcept {
this->MoveToRAM();
return BaseClass::end();
}
ConstIterator end() const noexcept {
const_cast<Vector *>(this)->MoveToRAM();
return BaseClass::end();
}
auto rbegin() noexcept {
this->MoveToRAM();
return BaseClass::rbegin();
}
auto rbegin() const noexcept {
const_cast<Vector *>(this)->MoveToRAM();
return BaseClass::rbegin();
}
auto rend() noexcept {
this->MoveToRAM();
return BaseClass::rend();
}
auto rend() const noexcept {
const_cast<Vector *>(this)->MoveToRAM();
return BaseClass::rend();
}
void push_back(const T &x) {
this->MoveToRAM();
BaseClass::push_back(x);
}
void push_back(T &&x) {
this->MoveToRAM();
BaseClass::push_back(std::move(x));
}
template <typename... Args> reference emplace_back(Args &&...args) {
this->MoveToRAM();
return BaseClass::emplace_back(std::forward<Args>(args)...);
}
void pop_back() {
this->MoveToRAM();
BaseClass::pop_back();
}
template <typename... Args>
iterator emplace(const_iterator pos, Args &&...args) {
this->MoveToRAM();
return BaseClass::emplace(pos, std::forward<Args>(args)...);
}
iterator insert(const_iterator pos, const T &x) {
this->MoveToRAM();
return BaseClass::insert(pos, x);
}
iterator insert(const_iterator pos, T &&x) {
this->MoveToRAM();
return BaseClass::insert(pos, std::move(x));
}
template <typename InputIt>
iterator insert(const_iterator pos, InputIt first, InputIt last) {
this->MoveToRAM();
return BaseClass::insert(pos, first, last);
}
iterator erase(const_iterator pos) {
this->MoveToRAM();
return BaseClass::erase(pos);
}
iterator erase(const_iterator first, const_iterator last) {
this->MoveToRAM();
return BaseClass::erase(first, last);
}
void resize(size_t n) {
this->MoveToRAM();
BaseClass::resize(n);
}
void resize(size_t n, const T &x) {
this->MoveToRAM();
BaseClass::resize(n, x);
}
void reserve(size_t n) {
this->MoveToRAM();
BaseClass::reserve(n);
}
void clear() noexcept {
this->MoveToRAM();
BaseClass::clear();
}
template <typename InputIt> void assign(InputIt first, InputIt last) {
this->MoveToRAM();
BaseClass::assign(first, last);
}
void assign(size_type count, const T &value) {
this->MoveToRAM();
BaseClass::assign(count, value);
} }
void remove_element(unsigned int index) { void remove_element(unsigned int index) {
std::swap(Base::get()->at(index),Base::get()->back()); this->MoveToRAM();
Base::get()->pop_back(); std::swap(this->at(index), this->back());
this->pop_back();
}
void remove_element(T &t) {
this->MoveToRAM();
std::swap(t, this->back());
this->pop_back();
}
};
template <typename T> void Vector<T>::PrintSelf(std::ostream &o) {
o << " *** uLib Vector *** \n";
o << " n. of items = " << this->size() << "\n";
for (int i = 0; i < this->size(); ++i)
o << (T)this->at(i) << " ";
o << "\n";
}
template <typename T>
std::ostream &operator<<(std::ostream &o, const Vector<T> &v) {
for (int i = 0; i < v.size(); ++i)
o << (T)v.at(i) << " ";
o << "\n";
return o;
}
template <typename T>
std::ofstream &operator<<(std::ofstream &o, const Vector<T> &v) {
for (int i = 0; i < v.size(); ++i)
o << (T)v.at(i) << " ";
return o;
}
template <typename T> std::istream &operator>>(std::istream &is, Vector<T> &v) {
T value;
while (is >> value) {
if (is.fail())
v.push_back(0);
else
v.push_back(value);
}
return is;
}
// Smart pointer Vector Implementation //
template <typename T> class SmartVector : public SmartPointer<Vector<T>> {
typedef SmartPointer<Vector<T>> Base;
public:
SmartVector() : Base(new Vector<T>()) {}
SmartVector(const SmartVector &copy) : Base(copy) {}
SmartVector(unsigned int size) : Base(new Vector<T>((int)size)) {}
virtual ~SmartVector() {}
T &operator[](int p) { return Base::get()->at(p); }
void swap_elements(unsigned int first, unsigned int second) {
std::swap(Base::get()->at(first), Base::get()->at(second));
}
void remove_element(unsigned int index) {
std::swap(Base::get()->at(index), Base::get()->back());
Base::get()->pop_back();
} }
void remove_element(T &t) { void remove_element(T &t) {
std::swap(t, Base::get()->back()); std::swap(t, Base::get()->back());
Base::get()->pop_back(); Base::get()->pop_back();
} }
}; };
// ------ Utils ------------------------------------------------------------- // // ------ Utils ------------------------------------------------------------- //
// RIFARE con iteratore ! // RIFARE con iteratore !
template <typename _Tp, class _CmpT> template <typename _Tp, class _CmpT>
inline const unsigned long inline unsigned long VectorSplice(const _Tp &_it, const _Tp &_end,
VectorSplice(const _Tp &_it, const _Tp &_end, const float value, _CmpT _comp) const float value, _CmpT _comp) {
{ _Tp it = _it;
_Tp it = _it; _Tp end = _end - 1;
_Tp end = _end-1; for (; it != end;) {
for(it; it != end;) if (_comp(*it, value))
{ ++it;
if (_comp(*it,value)) ++it; else if (_comp(*end, value))
else if(_comp(*end,value)) std::swap(*it,*end--); std::swap(*it, *end--);
else --end; else
} --end;
return it - _it; }
return it - _it;
} }
} // namespace uLib
} // uLib
#endif // VECTOR_H #endif // VECTOR_H

View File

@@ -8,7 +8,7 @@ set( TESTS
ObjectCopyTest ObjectCopyTest
StaticInterfaceTest StaticInterfaceTest
CommaInitTest CommaInitTest
DebugTTreeDumpTest # DebugTTreeDumpTest
BoostTest BoostTest
BoostAccumulatorTest BoostAccumulatorTest
PropertiesTest PropertiesTest
@@ -16,18 +16,23 @@ set( TESTS
SerializeTest SerializeTest
SerializeDreadDiamondTest SerializeDreadDiamondTest
DreadDiamondParameters DreadDiamondParameters
ObjectPropableTest
UuidTest UuidTest
TypeIntrospectionTraversal TypeIntrospectionTraversal
OptionsTest OptionsTest
PingPongTest
VectorMetaAllocatorTest
) )
set(LIBRARIES set(LIBRARIES
${PACKAGE_LIBPREFIX}Core ${PACKAGE_LIBPREFIX}Core
${PACKAGE_LIBPREFIX}Math ${PACKAGE_LIBPREFIX}Math
${Boost_SERIALIZATION_LIBRARY} Boost::serialization
${Boost_SIGNALS_LIBRARY} Boost::program_options
${Boost_PROGRAM_OPTIONS_LIBRARY}
${ROOT_LIBRARIES} ${ROOT_LIBRARIES}
) )
uLib_add_tests(${uLib-module}) uLib_add_tests(Core)
if(USE_CUDA)
set_source_files_properties(VectorMetaAllocatorTest.cpp PROPERTIES LANGUAGE CUDA)
endif()

View File

@@ -19,7 +19,6 @@ TESTS = SmartPointerTest \
SerializeTest \ SerializeTest \
SerializeDreadDiamondTest \ SerializeDreadDiamondTest \
DreadDiamondParameters \ DreadDiamondParameters \
ObjectPropableTest \
TypeIntrospectionTraversal \ TypeIntrospectionTraversal \
OptionsTest OptionsTest

View File

@@ -1,237 +0,0 @@
/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
------------------------------------------------------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
//////////////////////////////////////////////////////////////////////////////*/
#include <iostream>
#include <fstream>
#include <typeinfo>
#include <string>
#include "Core/Types.h"
#include "Core/Object.h"
#include "Core/ObjectProps.h"
#include "Core/StringReader.h"
#include "Math/Dense.h"
#include "boost/archive/text_oarchive.hpp"
#include "boost/archive/text_iarchive.hpp"
#include "testing-prototype.h"
using namespace uLib;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// STRUCTURES //
struct A : virtual Object {
uLibTypeMacro(A, Object)
properties() {
int p_a;
Vector3f p_3f;
};
int m_a;
};
void A::init_properties() {
$_init();
$$.p_a = 0;
$$.p_3f << 1,2,3;
}
ULIB_SERIALIZABLE_OBJECT(A)
ULIB_SERIALIZE_OBJECT(A, Object) { ar & AR(m_a); }
ULIB_SERIALIZE_OBJECT_PROPS(A) { ar & AR(p_a) & AR(p_3f); }
struct B : A {
uLibTypeMacro(B,A)
properties() {
std::string p;
};
B() : m_b(324) {}
int m_b;
};
void B::init_properties() {
$_init();
$$.p = "ciao";
}
ULIB_SERIALIZABLE_OBJECT(B)
ULIB_SERIALIZE_OBJECT(B,A) { ar & AR(m_b); }
ULIB_SERIALIZE_OBJECT_PROPS(B) { ar & AR(p); }
struct C {
int m_c;
std::string m_str;
};
ULIB_SERIALIZABLE(C)
ULIB_SERIALIZE(C) { ar & AR(m_c) & AR(m_str); }
struct D : virtual Object, B {
uLibTypeMacro(D,Object,B)
properties() {
C p_c;
};
};
void D::init_properties() {
$_init();
$$.p_c.m_c = 1234;
}
ULIB_SERIALIZABLE_OBJECT(D)
ULIB_SERIALIZE_OBJECT(D,Object) {}
ULIB_SERIALIZE_OBJECT_PROPS(D) {
ar & AR(p_c);
}
class E : public C, public D {
uLibTypeMacro(E,D,C)
public:
E() : m_Ea(5552368) {}
int m_Ea;
};
ULIB_SERIALIZABLE_OBJECT(E)
ULIB_SERIALIZE_OBJECT(E,C,D) {
ar & AR(m_Ea);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// TESTS //
int test_xml_direct() {
// TEST ARCHIVE SAVE AND LOAD direct //
E o; o.init_properties();
o.$$.p_c.m_str = "works";
{
std::ofstream file("test.xml");
Archive::xml_oarchive ar(file);
ar << NVP(o);
}
o.$$.p_c.m_str = "hola";
{
std::ifstream file("test.xml");
Archive::xml_iarchive ar(file);
ar >> NVP(o);
}
std::cout << o.$$.p_c.m_str << "\n";
return ( o.$$.p_c.m_str == "works" );
}
int test_xml_pointer() {
// TEST ARCHIVE SAVE AND LOAD from pointer //
E *o = new E; o->init_properties();
o->$$.p_c.m_str = "works";
{
std::ofstream file("test.xml");
Archive::xml_oarchive ar(file);
ar << NVP(o);
}
o->$$.p_c.m_str = "hola";
{
std::ifstream file("test.xml");
Archive::xml_iarchive ar(file);
ar >> NVP(o);
}
std::cout << o->$$.p_c.m_str << "\n";
return ( o->$$.p_c.m_str == "works" );
}
int test_xml_objsave() {
// TEST SELF SAVE
E o; o.init_properties();
o.$(B).p = "works";
{
std::ofstream file("test.xml");
Object::SaveXml(file,o);
}
o.$(B).p = "hola";
{
std::ifstream file("test.xml");
Object::LoadXml(file,o);
}
std::cout << o.$(B).p << "\n";
return ( o.$(B).p == "works" );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// MAIN //
int main()
{
BEGIN_TESTING(PropableTest);
TEST1( test_xml_direct() );
TEST1( test_xml_pointer() );
TEST1( test_xml_objsave() );
END_TESTING;
}

View File

@@ -0,0 +1,52 @@
#include "Core/Object.h"
#include "Core/Signal.h"
#include "testing-prototype.h"
#include <iostream>
using namespace uLib;
class Ping : public Object {
public:
signals:
void PingSignal(int count);
public slots:
void OnPong(int count) {
std::cout << "Ping received Pong " << count << std::endl;
if (count > 0)
ULIB_SIGNAL_EMIT(Ping::PingSignal, count - 1);
}
};
void Ping::PingSignal(int count) { ULIB_SIGNAL_EMIT(Ping::PingSignal, count); }
class Pong : public Object {
public:
signals:
void PongSignal(int count);
public slots:
void OnPing(int count) {
std::cout << "Pong received Ping " << count << std::endl;
if (count > 0)
ULIB_SIGNAL_EMIT(Pong::PongSignal, count - 1);
}
};
void Pong::PongSignal(int count) { ULIB_SIGNAL_EMIT(Pong::PongSignal, count); }
int main() {
BEGIN_TESTING(PingPong);
Ping ping;
Pong pong;
std::cout << "Connecting ping to pong" << std::endl;
Object::connect(&ping, &Ping::PingSignal, &pong, &Pong::OnPing);
std::cout << "Connecting pong to ping" << std::endl;
Object::connect(&pong, &Pong::PongSignal, &ping, &Ping::OnPong);
std::cout << "Emitting PingSignal(5)" << std::endl;
ping.PingSignal(5);
END_TESTING;
return 0;
}

View File

@@ -23,13 +23,10 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include <iostream>
#include <fstream> #include <fstream>
#include <typeinfo> #include <iostream>
#include <string> #include <string>
#include <typeinfo>
#include "Core/Object.h" #include "Core/Object.h"
@@ -37,78 +34,43 @@
using namespace uLib; using namespace uLib;
struct A : Object {
uLibTypeMacro(A, Object) A() : numa(5552368) {}
int numa;
struct A : Object {
uLibTypeMacro(A,Object)
A() : numa(5552368) {}
int numa;
}; };
ULIB_SERIALIZABLE_OBJECT(A) ULIB_SERIALIZABLE_OBJECT(A)
ULIB_SERIALIZE_OBJECT(A,Object) { ULIB_SERIALIZE_OBJECT(A, Object) { ar &AR(numa); }
ar & AR(numa);
}
struct B : virtual Object { struct B : virtual Object {
uLibTypeMacro(B,Object) uLibTypeMacro(B, Object) B() : numb(5552369) {}
B() : numb(5552369) {} int numb;
int numb;
}; };
ULIB_SERIALIZABLE_OBJECT(B) ULIB_SERIALIZABLE_OBJECT(B)
ULIB_SERIALIZE_OBJECT(B,Object) { ar & AR(numb); } ULIB_SERIALIZE_OBJECT(B, Object) { ar &AR(numb); }
struct C : B { struct C : B {
uLibTypeMacro(C,B) uLibTypeMacro(C, B) C() : numc(5552370) {}
C() : numc(5552370) {} int numc;
int numc;
}; };
ULIB_SERIALIZABLE_OBJECT(C) ULIB_SERIALIZABLE_OBJECT(C)
ULIB_SERIALIZE_OBJECT(C,B) { ar & AR(numc); } ULIB_SERIALIZE_OBJECT(C, B) { ar &AR(numc); }
struct D : A,B { struct D : A, B {
uLibTypeMacro(D,A,B) uLibTypeMacro(D, A, B)
D() : numd(5552371) {} D()
int numd; : numd(5552371) {}
int numd;
}; };
ULIB_SERIALIZABLE_OBJECT(D) ULIB_SERIALIZABLE_OBJECT(D)
ULIB_SERIALIZE_OBJECT(D,A,B) { ar & AR(numd); } ULIB_SERIALIZE_OBJECT(D, A, B) { ar &AR(numd); }
int main() {
A o;
Archive::xml_oarchive(std::cout) << NVP(o);
main() {
A o; o.init_properties();
Archive::xml_oarchive(std::cout) << NVP(o);
} }

View File

@@ -23,20 +23,16 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include <iostream>
#include <fstream> #include <fstream>
#include <iostream>
#include "Core/Object.h"
#include "Core/Archives.h" #include "Core/Archives.h"
#include "Core/Object.h"
#include "testing-prototype.h" #include "testing-prototype.h"
using namespace uLib; using namespace uLib;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -45,63 +41,51 @@ using namespace uLib;
struct V3f { struct V3f {
float x,y,z; float x, y, z;
V3f() V3f() { x = y = z = 0; }
{ x = y = z =0; }
V3f(float x, float y, float z) : V3f(float x, float y, float z) : x(x), y(y), z(z) {}
x(x), y(y), z(z) {}
template <class Archive> template <class Archive> void serialize(Archive &ar, unsigned int v) {
void serialize (Archive &ar,unsigned int v) { ar & "<" & NVP(x) & NVP(y) & NVP(z) & ">";
ar }
& "<" & NVP(x) & NVP(y) & NVP(z) & ">";
}
}; };
ULIB_CLASS_EXPORT_KEY(V3f); ULIB_CLASS_EXPORT_KEY(V3f);
ULIB_CLASS_EXPORT_IMPLEMENT(V3f); ULIB_CLASS_EXPORT_IMPLEMENT(V3f);
inline std::ostream &operator<<(std::ostream &o, const V3f &v) {
inline std::ostream & Archive::hrt_oarchive(o) << v;
operator <<(std::ostream &o, const V3f &v) { return o;
Archive::hrt_oarchive(o) << v;
return o;
} }
inline std::istream & inline std::istream &operator>>(std::istream &is, V3f &v) {
operator >>(std::istream &is, V3f &v) { Archive::hrt_iarchive(is) >> v;
Archive::hrt_iarchive(is) >> v; return is;
return is;
} }
int test_V3f() { int test_V3f() {
// testing human readble archive with simple serializable structure // // testing human readble archive with simple serializable structure //
V3f v1(1,2,3),v2,v3,v4; V3f v1(1, 2, 3), v2, v3, v4;
std::cout << "v --> " << v1 << "\n"; std::cout << "v --> " << v1 << "\n";
std::stringstream ss; ss << v1; std::stringstream ss;
std::cout << "ss.v --> " << ss.str() << "\n"; ss << v1;
std::cout << "ss.v --> " << ss.str() << "\n";
Archive::hrt_iarchive ar(ss); ar >> v2; Archive::hrt_iarchive ar(ss);
std::cout << "v2 --> " << v2 << "\n"; ar >> v2;
std::cout << "v2 --> " << v2 << "\n";
std::stringstream("<2 3 4>") >> v3; std::stringstream("<2 3 4>") >> v3;
std::cout << "v3 --> " << v3 << "\n"; std::cout << "v3 --> " << v3 << "\n";
// std::cout << "insert V3f string to parse: "; std::cin >> v4; // std::cout << "insert V3f string to parse: "; std::cin >> v4;
// std::cout << "v4 --> " << v4 << "\n"; // std::cout << "v4 --> " << v4 << "\n";
return (1); return (1);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -109,104 +93,72 @@ int test_V3f() {
// OBJECT SERIALIZATION // // OBJECT SERIALIZATION //
class A : public virtual Object { class A : public virtual Object {
uLibTypeMacro(A,Object) uLibTypeMacro(A, Object) ULIB_SERIALIZE_ACCESS public : A() : m_a(5552368) {}
ULIB_SERIALIZE_ACCESS
public:
A() : m_a(5552368) {}
properties() { void init_properties();
std::string p_a; std::string p_a;
};
uLibRefMacro(a, int);
uLibRefMacro (a,int);
private: private:
int m_a; int m_a;
}; };
void A::init_properties() { void A::init_properties() { p_a = "A property string"; }
$_init();
$$.p_a = "A property string";
}
ULIB_SERIALIZABLE_OBJECT(A) ULIB_SERIALIZABLE_OBJECT(A)
ULIB_SERIALIZE_OBJECT(A,Object) { ULIB_SERIALIZE_OBJECT(A, Object) {
ar ar & "Object A : " & "--> m_a = " & AR(m_a) & "\n" & "Object A properties: " &
& "Object A : " "---> p_a = " & AR(p_a) & "\n";
& "--> m_a = " & AR(m_a)
& "\n";
} }
ULIB_SERIALIZE_OBJECT_PROPS(A) {
ar
& "Object A properties: "
& "---> p_a = " & AR(p_a) & "\n";
}
int testing_xml_class() { int testing_xml_class() {
A a; a.init_properties(); A a;
a.init_properties();
{ {
std::ofstream file("test.xml"); std::ofstream file("test.xml");
Archive::xml_oarchive(file) << NVP(a); Archive::xml_oarchive(file) << NVP(a);
} }
a.a() = 0; a.a() = 0;
a.$$.p_a = "zero string"; a.p_a = "zero string";
{ {
std::ifstream file("test.xml"); std::ifstream file("test.xml");
Archive::xml_iarchive(file) >> NVP(a); Archive::xml_iarchive(file) >> NVP(a);
} }
Archive::xml_oarchive(std::cout) << NVP(a); Archive::xml_oarchive(std::cout) << NVP(a);
return ( a.a() == 5552368 && a.$$.p_a == "A property string" ); return (a.a() == 5552368 && a.p_a == "A property string");
} }
int testing_hrt_class() { int testing_hrt_class() {
A a; a.init_properties(); A a;
a.init_properties();
{ {
std::ofstream file("test.xml"); std::ofstream file("test.xml");
Archive::hrt_oarchive(file) << NVP(a); Archive::hrt_oarchive(file) << NVP(a);
} }
a.a() = 0; a.a() = 0;
a.$$.p_a = "zero string"; a.p_a = "zero string";
{ {
// ERRORE FIX ! // ERRORE FIX !
// std::ifstream file("test.xml"); // std::ifstream file("test.xml");
// Archive::hrt_iarchive(file) >> NVP(a); // Archive::hrt_iarchive(file) >> NVP(a);
} }
Archive::hrt_oarchive(std::cout) << NVP(a); Archive::hrt_oarchive(std::cout) << NVP(a);
return ( a.a() == 5552368 && a.$$.p_a == "A property string" ); return (a.a() == 5552368 && a.p_a == "A property string");
} }
int main() { int main() {
BEGIN_TESTING(Serialize Test); BEGIN_TESTING(Serialize Test);
TEST1( test_V3f() ); TEST1(test_V3f());
TEST1( testing_xml_class() ); TEST1(testing_xml_class());
// testing_hrt_class(); ///// << ERRORE in HRT with properties // testing_hrt_class(); ///// << ERRORE in HRT with properties
END_TESTING; END_TESTING;
} }

View File

@@ -23,93 +23,63 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include <iostream> #include <iostream>
#include <typeinfo> #include <typeinfo>
#include "testing-prototype.h"
#include "Core/Types.h"
#include "Core/Object.h" #include "Core/Object.h"
#include "Core/Signal.h" #include "Core/Signal.h"
#include "Core/Types.h"
#include "testing-prototype.h"
using namespace uLib; using namespace uLib;
class Ob1 : public Object { class Ob1 : public Object {
public: public:
signals: signals:
void V0(); void V0();
int V1(int a);
void V1(int a);
}; };
// should be done by moc // // should be done by moc //
void Ob1::V0() { void Ob1::V0() { ULIB_SIGNAL_EMIT(Ob1::V0); }
ULIB_SIGNAL_EMIT(Ob1::V0);
}
int Ob1::V1(int a) {
ULIB_SIGNAL_EMIT(Ob1::V1,a);
}
void Ob1::V1(int a) { ULIB_SIGNAL_EMIT(Ob1::V1, a); }
class Ob2 : public Object { class Ob2 : public Object {
public slots: public slots:
void PrintV0() { void PrintV0() { std::cout << "Ob2 prints V0\n" << std::flush; }
std::cout << "Ob2 prints V0\n" << std::flush;
}
}; };
class Ob3 : public Object { class Ob3 : public Object {
public slots: public slots:
void PrintV0() { void PrintV0() { std::cout << "Ob3 prints V0\n" << std::flush; }
std::cout << "Ob3 prints V0\n" << std::flush;
}
void PrintNumber(int n) { void PrintNumber(int n) {
std::cout << "Ob3 is printing number: " << n << "\n"; std::cout << "Ob3 is printing number: " << n << "\n";
} }
}; };
int main() { int main() {
BEGIN_TESTING(Signals); BEGIN_TESTING(Signals);
Ob1 ob1; Ob1 ob1;
Ob2 ob2; Ob2 ob2;
Ob3 ob3; Ob3 ob3;
Object::connect(&ob1,&Ob1::V0,&ob2,&Ob2::PrintV0); Object::connect(&ob1, &Ob1::V0, &ob2, &Ob2::PrintV0);
Object::connect(&ob1,&Ob1::V0,&ob3,&Ob3::PrintV0); Object::connect(&ob1, &Ob1::V0, &ob3, &Ob3::PrintV0);
Object::connect(&ob1,&Ob1::V1,&ob3,&Ob3::PrintNumber); Object::connect(&ob1, &Ob1::V1, &ob3, &Ob3::PrintNumber);
// not working yet // not working yet
// Object::connect(&ob1,SIGNAL(V0(),&ob2,SLOT(PrintV0()) // Object::connect(&ob1,SIGNAL(V0(),&ob2,SLOT(PrintV0())
ob1.PrintSelf(std::cout); ob1.PrintSelf(std::cout);
emit ob1.V0(); emit ob1.V0();
emit ob1.V1(5552368); emit ob1.V1(5552368);
END_TESTING; END_TESTING;
} }

View File

@@ -23,90 +23,73 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include <iostream> #include <iostream>
#include "testing-prototype.h" #include "testing-prototype.h"
#include <Core/StaticInterface.h> #include <Core/StaticInterface.h>
namespace uLib { namespace uLib {
//// INTERFACE TO COMPLEX CLASS ///// //// INTERFACE TO COMPLEX CLASS /////
namespace Interface { namespace Interface {
struct Test { struct Test {
MAKE_TRAITS MAKE_TRAITS
template<class Self> void check_structural() { template <class Self> void check_structural() {
uLibCheckFunction(Self,test,bool,int,float); uLibCheckFunction(Self, test, bool, int, float);
uLibCheckMember(Self,testmemb,int); uLibCheckMember(Self, testmemb, int);
} }
}; };
} } // namespace Interface
struct Test { struct Test {
bool test(int i, float f){} bool test(int i, float f) { return true; }
int testmemb; int testmemb;
}; };
//// INTERFAC TO SIMPLE CLASS /////////// //// INTERFAC TO SIMPLE CLASS ///////////
namespace Interface { namespace Interface {
struct Simple { struct Simple {
MAKE_TRAITS MAKE_TRAITS
template<class Self> void check_structural() { template <class Self> void check_structural() {
uLibCheckMember(Self,memb1,int); uLibCheckMember(Self, memb1, int);
uLibCheckMember(Self,memb2,float); uLibCheckMember(Self, memb2, float);
} }
}; };
} } // namespace Interface
struct Simple { struct Simple {
int memb1; int memb1;
float memb2; float memb2;
}; };
///////////////////////// /////////////////////////
template <class T> template <class T> class UseTest {
class UseTest {
public: public:
UseTest() { UseTest() {
Interface::IsA<T,Interface::Test>(); Interface::IsA<T, Interface::Test>();
T t; T t;
int i; float f; int i;
t.test(i,f); float f;
} t.test(i, f);
}
}; };
template <class T> template <class T> class UseSimple {
class UseSimple {
public: public:
UseSimple() { UseSimple() { Interface::IsA<T, Interface::Simple>(); }
Interface::IsA<T,Interface::Simple>();
}
}; };
} // namespace uLib
int main() {
BEGIN_TESTING(Static Interface);
uLib::UseTest<uLib::Test> u;
uLib::UseSimple<uLib::Simple> s;
END_TESTING;
} }
int main()
{
BEGIN_TESTING(Static Interface);
uLib::UseTest<uLib::Test> u;
uLib::UseSimple<uLib::Simple> s;
END_TESTING;
}

View File

@@ -0,0 +1,97 @@
/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
//////////////////////////////////////////////////////////////////////////////*/
#include "testing-prototype.h"
#include <Core/Vector.h>
#ifdef USE_CUDA
#include <thrust/device_ptr.h>
#include <thrust/transform.h>
struct DoubleFunctor {
__host__ __device__ int operator()(int x) const { return x * 2; }
};
#endif
int main() {
BEGIN_TESTING(VectorMetaAllocator);
uLib::Vector<int> v;
std::cout << "Pushing elements...\n";
v << 1, 2, 3, 4, 5;
std::cout << "Initial RAM contents: ";
for (size_t i = 0; i < v.size(); ++i) {
std::cout << v[i] << " ";
if (v[i] != (int)(i + 1)) {
std::cout << "\nError: Value mismatch at index " << i << "\n";
exit(1);
}
}
std::cout << "\n";
#ifdef USE_CUDA
std::cout << "Moving to VRAM...\n";
v.MoveToVRAM();
int *vram_ptr = v.GetVRAMData();
if (vram_ptr) {
std::cout << "Successfully obtained VRAM pointer: " << vram_ptr << "\n";
} else {
std::cout << "Error: Failed to obtain VRAM pointer!\n";
exit(1);
}
// Verify DeviceData() matches GetVRAMData()
{
thrust::device_ptr<int> dev_ptr = v.DeviceData();
if (dev_ptr.get() != vram_ptr) {
std::cout << "Error: DeviceData() does not match GetVRAMData()!\n";
exit(1);
}
std::cout << "DeviceData() matches GetVRAMData(). OK\n";
}
// Use thrust::transform via DeviceBegin()/DeviceEnd() to double all elements
// on device
std::cout << "Doubling elements on device via thrust::transform...\n";
thrust::transform(v.DeviceBegin(), v.DeviceEnd(), v.DeviceBegin(),
DoubleFunctor{});
std::cout << "Moving back to RAM...\n";
v.MoveToRAM();
std::cout << "RAM contents after VRAM trip + thrust transform: ";
for (size_t i = 0; i < v.size(); ++i) {
std::cout << v[i] << " ";
if (v[i] != (int)((i + 1) * 2)) {
std::cout << "\nError: Data corrupted after RAM->VRAM->thrust->RAM trip "
"at index "
<< i << "\n";
exit(1);
}
}
std::cout << "\n";
#else
std::cout << "USE_CUDA not defined, skipping VRAM tests.\n";
#endif
std::cout << "Scaling vector...\n";
for (size_t i = 0; i < v.size(); ++i)
v[i] *= 10;
std::cout << "Final contents: ";
for (size_t i = 0; i < v.size(); ++i)
std::cout << v[i] << " ";
std::cout << "\n";
END_TESTING;
}

View File

@@ -23,62 +23,47 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include <Core/Vector.h>
#include "testing-prototype.h" #include "testing-prototype.h"
#include <Core/Vector.h>
#include <algorithm> #include <algorithm>
template < typename T > template <typename T> struct __Cmp {
struct __Cmp { bool operator()(const T &data, const float value) { return data <= value; }
bool operator()(const T &data, const float value) {
return data <= value;
}
}; };
template <typename _Tp, typename _CmpT>
inline const unsigned long VectorSplice(const _Tp &_it, const _Tp &_end,
const float value, _CmpT _comp) {
_Tp it = _it;
_Tp end = _end - 1;
template<typename _Tp, typename _CmpT> for (it; it != end;) {
inline const unsigned long if (_comp(*it, value))
VectorSplice(const _Tp &_it, const _Tp &_end, const float value, _CmpT _comp) it++;
{ else if (_comp(*end, value)) {
std::swap(*it, *end--);
_Tp it = _it; } else
_Tp end = _end-1; --end;
for(it; it != end; ) }
{ return it - _it;
if ( _comp(*it, value) ) it++;
else if( _comp(*end, value) )
{
std::swap(*it,*end--);
}
else --end;
}
return it - _it;
} }
int main() {
BEGIN_TESTING(Vector);
int main() uLib::Vector<float> v;
{ v << 5, 4, 3, 2, 6, 1, 2, 3, 65, 7, 32, 23, 4, 3, 45, 4, 34, 3, 4, 4, 3, 3, 4,
BEGIN_TESTING(Vector); 2, 2, 3;
uLib::Vector<float> v; int id = ::VectorSplice(v.begin(), v.end(), 3, __Cmp<float>());
v << 5,4,3,2,6,1,2,3,65,7,32,23,4,3,45,4,34,3,4,4,3,3,4,2,2,3;
std::cout << "id: " << id << "\n";
std::cout << "vector: ";
for (uLib::Vector<float>::Iterator it = v.begin(); it != v.end(); it++)
std::cout << *it << " ";
std::cout << std::endl;
// std::sort(v.begin(),v.end(),LT<float>());
END_TESTING;
int id = VectorSplice(v.begin(),v.end(),3,__Cmp<float>());
std::cout << "id: " << id << "\n";
std::cout << "vector: ";
for(uLib::Vector<float>::Iterator it = v.begin(); it!=v.end(); it++)
std::cout << *it <<" ";
std::cout << std::endl;
// std::sort(v.begin(),v.end(),LT<float>());
END_TESTING;
} }

View File

@@ -2,5 +2,11 @@ set(HEADERS MuonScatter.h MuonError.h MuonEvent.h)
set(ULIB_SELECTED_MODULES ${ULIB_SELECTED_MODULES} Detectors PARENT_SCOPE) set(ULIB_SELECTED_MODULES ${ULIB_SELECTED_MODULES} Detectors PARENT_SCOPE)
install(FILES ${HEADERS} install(FILES ${HEADERS}
DESTINATION ${PACKAGE_INSTALL_INC_DIR}/Detectors) DESTINATION ${INSTALL_INC_DIR}/Detectors)
if(BUILD_TESTING)
include(uLibTargetMacros)
add_subdirectory(testing)
endif()

View File

@@ -1,18 +1,15 @@
# TESTS # TESTS
set( TESTS set( TESTS
GDMLSolidTest # GDMLSolidTest
HierarchicalEncodingTest HierarchicalEncodingTest
) )
#set(LIBRARIES set(LIBRARIES
# ${PACKAGE_LIBPREFIX}Core ${PACKAGE_LIBPREFIX}Core
# ${PACKAGE_LIBPREFIX}Math ${PACKAGE_LIBPREFIX}Math
# ${PACKAGE_LIBPREFIX}Detectors Boost::serialization
# ${Boost_SERIALIZATION_LIBRARY} Boost::program_options
# ${Boost_SIGNALS_LIBRARY} Eigen3::Eigen
# ${Boost_PROGRAM_OPTIONS_LIBRARY} ${ROOT_LIBRARIES}
# ${Eigen_LIBRARY} )
# ${Geant4_LIBRARIES} uLib_add_tests(Detectors)
# ${ROOT_LIBRARIES}
#)
uLib_add_tests(${uLib-module})

View File

@@ -1,35 +0,0 @@
# SUBDIRS = .
include $(top_srcdir)/Common.am
DISTSOURCES = vtkviewport.cpp main.cpp
DISTHEADERS_MOC =
DISTHEADERS_NO_MOC =
FORMS = vtkviewport.ui
FORMHEADERS = $(FORMS:.ui=.h)
MOC_CC = $(FORMS:.ui=.moc.cpp) $(DISTHEADERS_MOC:.h=.moc.cpp)
bin_PROGRAMS = QTVtkViewport
BUILT_SOURCES = $(FORMHEADERS) $(MOC_CC)
CLEANFILES = $(BUILT_SOURCES)
EXTRA_DIST = $(FORMS)
QTVtkViewport_SOURCES = $(DISTSOURCES) $(DISTHEADERS_MOC) $(DISTHEADERS_NO_MOC)
nodist_QTVtkViewport_SOURCES = $(MOC_CC)
QTVtkViewport_LDADD = $(top_srcdir)/libmutom.la
.ui.h: $(FORMS)
$(UIC) -o ui_$@ $<
.ui.hpp: $(FORMS_HPP)
$(UIC) -o $@ $<
.h.moc.cpp:
$(MOC) -o $@ $<
SUFFIXES = .h .ui .moc.cpp

View File

@@ -1,18 +0,0 @@
#-------------------------------------------------
#
# Project created by QtCreator 2012-08-30T18:59:53
#
#-------------------------------------------------
QT += core gui
TARGET = QVTKViewport2
TEMPLATE = app
SOURCES += main.cpp\
vtkviewport.cpp
HEADERS += vtkviewport.h
FORMS += vtkviewport.ui

View File

@@ -1,453 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by Qt Creator 2.4.1, 2012-09-03T09:43:56. -->
<qtcreator>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QString" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QString" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">System</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">1</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap"/>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Target.DesktopTarget</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildCOnfiguration.ToolChain">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.gdb</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 4.7.4 for GCC (Qt SDK) Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="QString" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory">/home/andrea/devel/MuonTomography/mutom/uLib/trunk/src/Gui/Qt/QVTKViewport2</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId">3</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildCOnfiguration.ToolChain">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.gdb</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 4.7.4 for GCC (Qt SDK) Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="QString" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory">/home/andrea/devel/MuonTomography/mutom/uLib/trunk/src/Gui/Qt/QVTKViewport2</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId">3</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="QString" key="ProjectExplorer.BuildCOnfiguration.ToolChain">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.gdb</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Qt 4.7.0 in PATH (System) Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="QString" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory">/home/andrea/devel/MuonTomography/mutom/uLib/trunk/src/Gui/Qt/QVTKViewport2</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId">4</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.3">
<value type="QString" key="ProjectExplorer.BuildCOnfiguration.ToolChain">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.gdb</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Qt 4.7.0 in PATH (System) Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="QString" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory">/home/andrea/devel/MuonTomography/mutom/uLib/trunk/src/Gui/Qt/QVTKViewport2</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId">4</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.4">
<value type="QString" key="ProjectExplorer.BuildCOnfiguration.ToolChain">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.gdb</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Qt 4.7.0 (System) Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="QString" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory">/home/andrea/devel/MuonTomography/mutom/uLib/trunk/src/Gui/Qt/QVTKViewport2</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId">5</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.5">
<value type="QString" key="ProjectExplorer.BuildCOnfiguration.ToolChain">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.gdb</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Qt 4.7.0 (System) Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="QString" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory">/home/andrea/devel/MuonTomography/mutom/uLib/trunk/src/Gui/Qt/QVTKViewport2</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId">5</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">6</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">No deployment</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Project.UseGlobal">true</value>
<value type="bool" key="Analyzer.Project.UseGlobal">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">false</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">false</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
</valuelist>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
</valuelist>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">QVTKViewport2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase">2</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">QVTKViewport2.pro</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">false</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.EnvironmentId</variable>
<value type="QString">{f8bb0047-7f6e-45df-9cc8-e746abebf883}</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">10</value>
</data>
</qtcreator>

View File

@@ -1,38 +0,0 @@
/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
------------------------------------------------------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
//////////////////////////////////////////////////////////////////////////////*/
#include <QtGui/QApplication>
#include "vtkviewport.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
VtkViewport w;
w.show();
return a.exec();
}

View File

@@ -1,41 +0,0 @@
/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
------------------------------------------------------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
//////////////////////////////////////////////////////////////////////////////*/
#include "vtkviewport.h"
#include "ui_vtkviewport.h"
VtkViewport::VtkViewport(QWidget *parent) :
QWidget(parent),
ui(new Ui::VtkViewport)
{
ui->setupUi(this);
}
VtkViewport::~VtkViewport()
{
delete ui;
}

View File

@@ -1,49 +0,0 @@
/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
------------------------------------------------------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
//////////////////////////////////////////////////////////////////////////////*/
#ifndef VTKVIEWPORT_H
#define VTKVIEWPORT_H
#include <QWidget>
namespace Ui {
class VtkViewport;
}
class VtkViewport : public QWidget
{
Q_OBJECT
public:
explicit VtkViewport(QWidget *parent = 0);
~VtkViewport();
private:
Ui::VtkViewport *ui;
};
#endif // VTKVIEWPORT_H

View File

@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VtkViewport</class>
<widget class="QWidget" name="VtkViewport">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>580</width>
<height>536</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>140</x>
<y>170</y>
<width>161</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>Hello World !</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -27,6 +27,8 @@
#ifndef U_MATH_BITCODE_H #ifndef U_MATH_BITCODE_H
#define U_MATH_BITCODE_H #define U_MATH_BITCODE_H
#include <iostream>
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include <boost/type_traits.hpp> #include <boost/type_traits.hpp>
#include <boost/mpl/vector_c.hpp> #include <boost/mpl/vector_c.hpp>
@@ -34,6 +36,7 @@
#include <Math/Dense.h> #include <Math/Dense.h>
namespace uLib { namespace uLib {

View File

@@ -1,3 +1,4 @@
set(HEADERS ContainerBox.h set(HEADERS ContainerBox.h
Dense.h Dense.h
Geometry.h Geometry.h
@@ -31,8 +32,9 @@ set(SOURCES VoxRaytracer.cpp
Structured2DGrid.cpp Structured2DGrid.cpp
Structured4DGrid.cpp) Structured4DGrid.cpp)
set(LIBRARIES ${Eigen_LIBRARY} set(LIBRARIES Eigen3::Eigen
${ROOT_LIBRARIES}) ${ROOT_LIBRARIES}
${VTK_LIBRARIES})
set(libname ${PACKAGE_LIBPREFIX}Math) set(libname ${PACKAGE_LIBPREFIX}Math)
set(ULIB_SHARED_LIBRARIES ${ULIB_SHARED_LIBRARIES} ${libname} PARENT_SCOPE) set(ULIB_SHARED_LIBRARIES ${ULIB_SHARED_LIBRARIES} ${libname} PARENT_SCOPE)
@@ -41,13 +43,25 @@ set(ULIB_SELECTED_MODULES ${ULIB_SELECTED_MODULES} Math PARENT_SCOPE)
add_library(${libname} SHARED ${SOURCES}) add_library(${libname} SHARED ${SOURCES})
set_target_properties(${libname} PROPERTIES set_target_properties(${libname} PROPERTIES
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_SOVERSION}) SOVERSION ${PROJECT_SOVERSION}
CXX_STANDARD 17
CUDA_STANDARD 17)
target_link_libraries(${libname} ${LIBRARIES}) target_link_libraries(${libname} ${LIBRARIES})
if(USE_CUDA)
set_source_files_properties(VoxRaytracer.cpp VoxImage.cpp PROPERTIES LANGUAGE CUDA)
endif()
install(TARGETS ${libname} install(TARGETS ${libname}
EXPORT "${PROJECT_NAME}Targets" EXPORT "${PROJECT_NAME}Targets"
RUNTIME DESTINATION ${PACKAGE_INSTALL_BIN_DIR} COMPONENT bin RUNTIME DESTINATION ${INSTALL_BIN_DIR} COMPONENT bin
LIBRARY DESTINATION ${PACKAGE_INSTALL_LIB_DIR} COMPONENT lib) LIBRARY DESTINATION ${INSTALL_LIB_DIR} COMPONENT lib)
install(FILES ${HEADERS} DESTINATION ${PACKAGE_INSTALL_INC_DIR}/Math) install(FILES ${HEADERS} DESTINATION ${INSTALL_INC_DIR}/Math)
if(BUILD_TESTING)
include(uLibTargetMacros)
add_subdirectory(testing)
endif()

View File

@@ -23,9 +23,6 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
/* /*
* <one line to give the program's name and a brief idea of what it does.> * <one line to give the program's name and a brief idea of what it does.>
* Copyright (C) 2012 Andrea Rigoni Garola <andrea@pcimg05> * Copyright (C) 2012 Andrea Rigoni Garola <andrea@pcimg05>
@@ -47,35 +44,37 @@
* *
*/ */
#ifndef ULIB_DENSEMATRIX_H #ifndef ULIB_DENSEMATRIX_H
#define ULIB_DENSEMATRIX_H #define ULIB_DENSEMATRIX_H
// #include <Eigen/src/Core/Matrix.h>
#include <stdlib.h> #include <stdlib.h>
#include <Eigen/Dense> #include <Eigen/Dense>
//// BOOST SERIALIZATION /////////////////////////////////////////////////////// //// BOOST SERIALIZATION ///////////////////////////////////////////////////////
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp> #include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/array.hpp> #include <boost/serialization/array.hpp>
#include <boost/serialization/string.hpp>
namespace boost { namespace boost {
namespace serialization { namespace serialization {
template<class Archive, class Scalar, int RowsAtCompileTime, int ColsAtCompileTime> template <class Archive, class Scalar, int RowsAtCompileTime,
void serialize(Archive & ar, ::Eigen::Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime> & m, const unsigned int /*version*/) { int ColsAtCompileTime>
ar & boost::serialization::make_array(m.data(), RowsAtCompileTime * ColsAtCompileTime); void serialize(Archive &ar,
::Eigen::Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime> &m,
const unsigned int /*version*/) {
ar &boost::serialization::make_array(m.data(),
RowsAtCompileTime * ColsAtCompileTime);
} }
} // serialization } // namespace serialization
} // boost } // namespace boost
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -84,60 +83,71 @@ void serialize(Archive & ar, ::Eigen::Matrix<Scalar, RowsAtCompileTime, ColsAtCo
// this is needed by boost::lexical_cast to cope with Eigens Vectors /////////// // this is needed by boost::lexical_cast to cope with Eigens Vectors ///////////
namespace Eigen { namespace Eigen {
template <typename T, int size> template <typename T, int size>
std::istream & operator >> (std::istream &is, Eigen::Matrix<T,size,1> &vec) { std::istream &operator>>(std::istream &is, Eigen::Matrix<T, size, 1> &vec) {
std::string str; std::string str;
for( unsigned int i=0; i<size; i++) { for (unsigned int i = 0; i < size; i++) {
is >> std::skipws; is >> std::skipws;
is >> str; is >> str;
if(is.fail()) vec(i) = 0; if (is.fail())
else vec(i) = boost::lexical_cast<T>(str); vec(i) = 0;
} else
return is; vec(i) = boost::lexical_cast<T>(str);
}
return is;
} }
template <typename T, int size> template <typename T, int size>
std::ostream & operator << (std::ostream &os, const Eigen::Matrix<T,size,1> &vec) { std::ostream &operator<<(std::ostream &os,
os << vec.transpose(); const Eigen::Matrix<T, size, 1> &vec) {
return os; os << vec.transpose();
return os;
} }
} // Eigen } // namespace Eigen
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace uLib { namespace uLib {
typedef id_t Id_t; typedef id_t Id_t;
typedef int Scalari; typedef int Scalari;
typedef unsigned int Scalarui; typedef unsigned int Scalarui;
typedef long Scalarl; typedef long Scalarl;
typedef unsigned long Scalarul; typedef unsigned long Scalarul;
typedef float Scalarf; typedef float Scalarf;
typedef double Scalard; typedef double Scalard;
typedef Eigen::Matrix<int, 1, 1> Vector1i;
typedef Eigen::Matrix<int,1,1> Matrix1i;
typedef Eigen::Matrix2i Matrix2i;
typedef Eigen::Matrix3i Matrix3i;
typedef Eigen::Matrix4i Matrix4i;
typedef Eigen::Matrix<float,1,1> Matrix1f;
typedef Eigen::Matrix2f Matrix2f;
typedef Eigen::Matrix3f Matrix3f;
typedef Eigen::Matrix4f Matrix4f;
typedef Eigen::Matrix<int,1,1> Vector1i;
typedef Eigen::Vector2i Vector2i; typedef Eigen::Vector2i Vector2i;
typedef Eigen::Vector3i Vector3i; typedef Eigen::Vector3i Vector3i;
typedef Eigen::Vector4i Vector4i; typedef Eigen::Vector4i Vector4i;
typedef Eigen::Matrix<float,1,1> Vector1f; typedef Eigen::Matrix<float, 1, 1> Vector1f;
typedef Eigen::Vector2f Vector2f; typedef Eigen::Vector2f Vector2f;
typedef Eigen::Vector3f Vector3f; typedef Eigen::Vector3f Vector3f;
typedef Eigen::Vector4f Vector4f; typedef Eigen::Vector4f Vector4f;
typedef Eigen::Matrix<double, 1, 1> Vector1d;
typedef Eigen::Vector2d Vector2d;
typedef Eigen::Vector3d Vector3d;
typedef Eigen::Vector4d Vector4d;
typedef Eigen::Matrix<int, 1, 1> Matrix1i;
typedef Eigen::Matrix2i Matrix2i;
typedef Eigen::Matrix3i Matrix3i;
typedef Eigen::Matrix4i Matrix4i;
typedef Eigen::Matrix<float, 1, 1> Matrix1f;
typedef Eigen::Matrix2f Matrix2f;
typedef Eigen::Matrix3f Matrix3f;
typedef Eigen::Matrix4f Matrix4f;
typedef Eigen::Matrix<double, 1, 1> Matrix1d;
typedef Eigen::Matrix2d Matrix2d;
typedef Eigen::Matrix3d Matrix3d;
typedef Eigen::Matrix4d Matrix4d;
typedef Eigen::MatrixXi MatrixXi;
typedef Eigen::MatrixXf MatrixXf;
typedef Eigen::MatrixXd MatrixXd;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -145,117 +155,109 @@ typedef Eigen::Vector4f Vector4f;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/*! Given a string consisting of a series of doubles with some /*! Given a string consisting of a series of doubles with some
* delimiter, return an Eigen::Vector populated with those * delimiter, return an Eigen::Vector populated with those
* values, in the same order as they are given in the string. * values, in the same order as they are given in the string.
* *
* \param vec A double vector to be populated with the results * \param vec A double vector to be populated with the results
* \param str A string to be parsed as a series of doubles. * \param str A string to be parsed as a series of doubles.
* \param delim Delimiters of the text (a typical default is " ," for comma and space-delimited text * \param delim Delimiters of the text (a typical default is " ," for comma and
* * space-delimited text
*/ *
*/
template <typename T, int size> template <typename T, int size>
void VectorxT_StringTo(Eigen::Matrix<T,size,1> &vec, std::string str, const char *delim = " ,;\t\n") { void VectorxT_StringTo(Eigen::Matrix<T, size, 1> &vec, std::string str,
std::vector<std::string> strvec; const char *delim = " ,;\t\n") {
std::vector<std::string> strvec;
boost::algorithm::trim_if( str, boost::algorithm::is_any_of(delim)); boost::algorithm::trim_if(str, boost::algorithm::is_any_of(delim));
boost::algorithm::split(strvec,str,boost::algorithm::is_any_of(delim), boost::algorithm::token_compress_on); boost::algorithm::split(strvec, str, boost::algorithm::is_any_of(delim),
boost::algorithm::token_compress_on);
for( unsigned int i=0; i<size; i++) { for (unsigned int i = 0; i < size; i++) {
vec(i) = boost::lexical_cast<T>(strvec[i]); vec(i) = boost::lexical_cast<T>(strvec[i]);
} }
} }
template <typename T, int size> template <typename T, int size>
std::string VectorxT_ToString(const Eigen::Matrix<T,size,1> &vec) { std::string VectorxT_ToString(const Eigen::Matrix<T, size, 1> &vec) {
std::stringstream sst; std::stringstream sst;
sst << vec.transpose(); sst << vec.transpose();
return sst.str(); return sst.str();
} }
// template <typename T, int size>
//template <typename T, int size> // Eigen::Matrix<T,size,1> & operator >> (std::istream &is,
//Eigen::Matrix<T,size,1> & operator >> (std::istream &is, Eigen::Matrix<T,size,1> &vec) { // Eigen::Matrix<T,size,1> &vec) {
//} // }
template <typename T, int size> template <typename T, int size>
void operator>> (std::string& str, Eigen::Matrix<T,size,1> &vec){ void operator >> (std::string &str, Eigen::Matrix<T, size, 1> &vec) {
VectorxT_StringTo(vec,str); VectorxT_StringTo(vec, str);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
////// HOMOGENEOUS VECTORS ////////////////////////////////////////////////// ////// HOMOGENEOUS VECTORS //////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <bool p> template <bool p> class _HPoint3f : public Eigen::Matrix<Scalarf, 4, 1> {
class _HPoint3f : public Eigen::Matrix< Scalarf,4,1 > {
public: public:
typedef Eigen::Matrix< Scalarf,4,1 > BaseClass; typedef Eigen::Matrix<Scalarf, 4, 1> BaseClass;
_HPoint3f<p>() : BaseClass(0,0,0,p) {} _HPoint3f() : BaseClass(0, 0, 0, p) {}
_HPoint3f<p>(float x,float y,float z) : BaseClass(x,y,z,p) {} _HPoint3f(int rows, int cols) : BaseClass() {
_HPoint3f<p>(Vector3f &in) : BaseClass(in.homogeneous()) { this->operator()(3) = p; } this->operator()(3) = p;
}
_HPoint3f(float x, float y, float z) : BaseClass(x, y, z, p) {}
_HPoint3f(Vector3f &in) : BaseClass(in.homogeneous()) {
this->operator()(3) = p;
}
void operator delete(void* _p, size_t _s) {} void operator delete(void *_p, size_t _s) {}
// This constructor allows to construct MyVectorType from Eigen expressions // This constructor allows to construct MyVectorType from Eigen expressions
template<typename OtherDerived> template <typename OtherDerived>
inline _HPoint3f<p>(const Eigen::MatrixBase<OtherDerived>& other) inline _HPoint3f(const Eigen::MatrixBase<OtherDerived> &other)
: BaseClass(other) : BaseClass(other) {}
{ }
// This method allows to assign Eigen expressions to Vector3H
template<typename OtherDerived>
inline _HPoint3f<p> & operator= (const Eigen::MatrixBase <OtherDerived>& other)
{
this->BaseClass::operator=(other);
return *this;
}
// This method allows to assign Eigen expressions to Vector3H
template <typename OtherDerived>
inline _HPoint3f &operator=(const Eigen::MatrixBase<OtherDerived> &other) {
this->BaseClass::operator=(other);
return *this;
}
}; };
typedef _HPoint3f<false> HVector3f; typedef _HPoint3f<false> HVector3f;
typedef _HPoint3f<true> HPoint3f; typedef _HPoint3f<true> HPoint3f;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
////// HOMOGENEOUS LINE ////////////////////////////////////////////////// ////// HOMOGENEOUS LINE //////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
struct _HLine3f {
struct _HLine3f HPoint3f origin;
{ HVector3f direction;
HPoint3f origin;
HVector3f direction;
}; };
typedef struct _HLine3f HLine3f; typedef struct _HLine3f HLine3f;
inline std::ostream& inline std::ostream &operator<<(std::ostream &stream, const HLine3f &line) {
operator<< (std::ostream& stream, const HLine3f &line) { stream << "HLine3f(" << "pt[" << line.origin.transpose() << "] , dr["
stream << "HLine3f(" << "pt[" << line.origin.transpose() <<"] , dr[" << line.direction.transpose() << "]) "; << line.direction.transpose() << "]) ";
return stream; return stream;
} }
struct _HError3f {
HVector3f position_error;
HVector3f direction_error;
struct _HError3f
{
HVector3f position_error;
HVector3f direction_error;
}; };
typedef struct _HError3f HError3f; typedef struct _HError3f HError3f;
inline std::ostream& inline std::ostream &operator<<(std::ostream &stream, const HError3f &err) {
operator<< (std::ostream& stream, const HError3f &err) { stream << "HError3f(" << "ept[" << err.position_error.transpose()
stream << "HError3f(" << "ept[" << err.position_error.transpose() <<"] , edr[" << err.direction_error.transpose() << "]) "; << "] , edr[" << err.direction_error.transpose() << "]) ";
return stream; return stream;
}
} }
} // namespace uLib
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -269,13 +271,9 @@ ULIB_SERIALIZABLE(uLib::HPoint3f)
ULIB_SERIALIZABLE(uLib::HVector3f) ULIB_SERIALIZABLE(uLib::HVector3f)
ULIB_SERIALIZABLE(uLib::HLine3f) ULIB_SERIALIZABLE(uLib::HLine3f)
ULIB_SERIALIZABLE(uLib::HError3f) ULIB_SERIALIZABLE(uLib::HError3f)
#endif // ULIB_SERIALIZATION_ON #endif // ULIB_SERIALIZATION_ON
#endif // U_DENSEMATRIX_H
#endif // U_DENSEMATRIX_H

View File

@@ -110,6 +110,17 @@ public:
inline void Rotate(const Matrix3f &m) { this->m_T.rotate(m); } inline void Rotate(const Matrix3f &m) { this->m_T.rotate(m); }
inline void Rotate(const float angle, Vector3f axis)
{
axis.normalize(); // prehaps not necessary ( see eigens )
Eigen::AngleAxisf ax(angle,axis);
this->m_T.rotate(Eigen::Quaternion<float>(ax));
}
inline void Rotate(const Vector3f euler_axis) {
float angle = euler_axis.norm();
Rotate(angle,euler_axis);
}
inline void PreRotate(const Matrix3f &m) { this->m_T.prerotate(m); } inline void PreRotate(const Matrix3f &m) { this->m_T.prerotate(m); }

View File

@@ -30,6 +30,13 @@
#include "VoxImage.h" #include "VoxImage.h"
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkXMLImageDataReader.h>
#include <vtkXMLImageDataWriter.h>
#include <vtkStringArray.h>
#include <vtkInformation.h>
#include <vtkInformationStringKey.h>
namespace uLib { namespace uLib {
@@ -83,7 +90,103 @@ void Abstract::VoxImage::ExportToVtk (const char *file, bool density_type)
printf("%s vtk file saved\n",file); printf("%s vtk file saved\n",file);
} }
int Abstract::VoxImage::ImportFromVtk(const char *file)
void Abstract::VoxImage::ExportToVti (const char *file, bool density_type, bool compressed)
{
Abstract::VoxImage *voxels = this;
vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();
image->SetDimensions(voxels->GetDims()(0), voxels->GetDims()(1), voxels->GetDims()(2));
image->SetSpacing(voxels->GetSpacing()(0), voxels->GetSpacing()(1), voxels->GetSpacing()(2));
image->SetOrigin(voxels->GetPosition()(0), voxels->GetPosition()(1), voxels->GetPosition()(2));
image->AllocateScalars(VTK_FLOAT, 1);
float norm;
if (density_type) {
norm = 1;
} else norm = 1.E6;
int nx = voxels->GetDims()(0);
int ny = voxels->GetDims()(1);
int nz = voxels->GetDims()(2);
size_t npoints = nx*ny*nz;
float *scalar = static_cast<float*>(image->GetScalarPointer());
StructuredData unwrap(*voxels);
unwrap.SetDataOrder(StructuredData::XYZ); // move to XYZ order (VTK)
for (size_t i = 0; i < npoints; i++) {
Vector3i idx = unwrap.UnMap(i);
scalar[i] = static_cast<float>(voxels->GetValue(idx) * norm);
}
// Create a custom string key
static vtkInformationStringKey* ConfigNote =
vtkInformationStringKey::MakeKey("cmt.config", "Config");
// Attach metadata
vtkInformation *info = image->GetInformation();
info->Set(ConfigNote,
"This image was generated with uLib\n"
"-----------------------------------\n"
"Author: Andrea Rigoni\n"
"Version: 0.1\n"
"Date: 2025\n"
);
// std::cout << info->Get(ConfigNote) << std::endl;
vtkSmartPointer<vtkXMLImageDataWriter> writer = vtkSmartPointer<vtkXMLImageDataWriter>::New();
writer->SetFileName(file);
writer->SetInputData(image);
if(compressed) {
writer->SetDataModeToBinary();
writer->SetCompressorTypeToZLib();
}
writer->Write();
}
int Abstract::VoxImage::ImportFromVti(const char *file, bool density_type) {
vtkSmartPointer<vtkXMLImageDataReader> reader = vtkSmartPointer<vtkXMLImageDataReader>::New();
reader->SetFileName(file);
reader->Update();
vtkImageData *image = reader->GetOutput();
if(!image) return false;
Abstract::VoxImage *voxels = this;
int nx = image->GetDimensions()[0];
int ny = image->GetDimensions()[1];
int nz = image->GetDimensions()[2];
voxels->SetDims(Vector3i(nx,ny,nz));
voxels->SetSpacing(Vector3f(image->GetSpacing()[0],image->GetSpacing()[1],image->GetSpacing()[2]));
voxels->SetPosition(Vector3f(image->GetOrigin()[0],image->GetOrigin()[1],image->GetOrigin()[2]));
float norm;
if (density_type) {
norm = 1;
} else norm = 1.E6;
size_t npoints = nx*ny*nz;
float *scalar = static_cast<float*>(image->GetScalarPointer());
StructuredData wrap(*voxels);
wrap.SetDataOrder(StructuredData::XYZ);
for (size_t i = 0; i < npoints; i++) {
Vector3i idx = wrap.UnMap(i);
voxels->SetValue(idx, scalar[i] / norm);
}
return true;
}
int Abstract::VoxImage::ImportFromVtk(const char *file, bool density_type)
{ {
FILE * vtk_file = fopen(file, "r"); FILE * vtk_file = fopen(file, "r");
if (!vtk_file) return false; if (!vtk_file) return false;
@@ -115,14 +218,18 @@ int Abstract::VoxImage::ImportFromVtk(const char *file)
this->SetSpacing(Vector3f(sx,sy,sz)); this->SetSpacing(Vector3f(sx,sy,sz));
this->SetPosition(Vector3f(ox,oy,oz)); this->SetPosition(Vector3f(ox,oy,oz));
float norm;
if (density_type) {
norm = 1;
} else norm = 1.E6;
for (int k = 0; k < dz; ++k) { for (int k = 0; k < dz; ++k) {
for (int j = 0; j < dy; ++j) { for (int j = 0; j < dy; ++j) {
for (int i = 0; i < dx; ++i) { for (int i = 0; i < dx; ++i) {
Vector3i idx(i, j, k); Vector3i idx(i, j, k);
float tmp_val; float tmp_val;
fscanf(vtk_file, "%f", &tmp_val); fscanf(vtk_file, "%f", &tmp_val);
//this->SetValue(idx,fabs(tmp_val)*1E-6); this->SetValue(idx,tmp_val / norm);
this->SetValue(idx,tmp_val*1E-6);
} }
} }
} }

View File

@@ -23,8 +23,6 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef U_MATH_VOXIMAGE_H #ifndef U_MATH_VOXIMAGE_H
#define U_MATH_VOXIMAGE_H #define U_MATH_VOXIMAGE_H
@@ -36,6 +34,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <vector> #include <vector>
#include <Core/DataAllocator.h>
namespace uLib { namespace uLib {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -46,26 +46,36 @@ namespace Abstract {
class VoxImage : public uLib::StructuredGrid { class VoxImage : public uLib::StructuredGrid {
public: public:
typedef uLib::StructuredGrid BaseClass; typedef uLib::StructuredGrid BaseClass;
virtual float GetValue(const Vector3i &id) const = 0; virtual float GetValue(const Vector3i &id) const = 0;
virtual float GetValue(const int id) const = 0; virtual float GetValue(const int id) const = 0;
virtual void SetValue(const Vector3i &id, float value) = 0; virtual void SetValue(const Vector3i &id, float value) = 0;
virtual void SetValue(const int id, float value) = 0; virtual void SetValue(const int id, float value) = 0;
virtual void SetDims(const Vector3i &size) = 0; virtual void SetDims(const Vector3i &size) = 0;
void ExportToVtk(const char *file, bool density_type = 0); void ExportToVtk(const char *file, bool density_type = 0);
void ExportToVtkXml(const char *file, bool density_type = 0);
int ImportFromVtk(const char *file);
// use this function to export to VTK binary format
void ExportToVti(const char *file, bool density_type = 0,
bool compressed = 0);
// this function has been deprecated in favor of ExportToVti
// but it is kept for backward compatibility and because it
// does not depend on vtk library
void ExportToVtkXml(const char *file, bool density_type = 0);
int ImportFromVtk(const char *file, bool density_type = 0);
int ImportFromVti(const char *file, bool density_type = 0);
virtual ~VoxImage() {}
protected: protected:
VoxImage(const Vector3i &size) : BaseClass(size) {}
virtual ~VoxImage() {}
VoxImage(const Vector3i &size) : BaseClass(size) {}
}; };
} } // namespace Abstract
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// VOXEL //////////////////////////////////////////////////////////////////// // VOXEL ////////////////////////////////////////////////////////////////////
@@ -73,421 +83,416 @@ protected:
namespace Interface { namespace Interface {
struct Voxel { struct Voxel {
template<class Self> void check_structural() { template <class Self> void check_structural() {
uLibCheckMember(Self,Value, Scalarf); uLibCheckMember(Self, Value, Scalarf);
} }
}; };
} } // namespace Interface
struct Voxel { struct Voxel {
Scalarf Value; Scalarf Value = 0.0f;
Scalari Count = 0;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// VOX IMAGE ///////////////////////////////////////////////////////////////// // VOX IMAGE /////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename T> class VoxImage : public Abstract::VoxImage {
template< typename T >
class VoxImage : public Abstract::VoxImage {
public: public:
typedef Abstract::VoxImage BaseClass; typedef Abstract::VoxImage BaseClass;
VoxImage(); VoxImage();
VoxImage(const Vector3i &size); VoxImage(const Vector3i &size);
VoxImage(const VoxImage<T> &copy) : VoxImage(const VoxImage<T> &copy) : BaseClass(copy) {
BaseClass(copy) this->m_Data = copy.m_Data;
{ }
this->m_Data = copy.m_Data;
inline DataAllocator<T> &Data() { return this->m_Data; }
inline const DataAllocator<T> &ConstData() const { return m_Data; }
inline const T &At(int i) const { return m_Data.at(i); }
inline const T &At(const Vector3i &id) const { return m_Data.at(Map(id)); }
inline T &operator[](unsigned int i) { return m_Data[i]; }
inline T &operator[](const Vector3i &id) { return m_Data[Map(id)]; }
// this implements Abstract interface //
inline Scalarf GetValue(const Vector3i &id) const {
return this->At(id).Value;
}
inline Scalarf GetValue(const int id) const { return this->At(id).Value; }
inline void SetValue(const Vector3i &id, Scalarf value) {
this->operator[](id).Value = value;
}
inline void SetValue(const int id, float value) {
this->operator[](id).Value = value;
}
inline void SetDims(const Vector3i &size) {
this->m_Data.resize(size.prod());
StructuredGrid::SetDims(size);
}
inline VoxImage<T> clipImage(const Vector3i begin, const Vector3i end) const;
inline VoxImage<T> clipImage(const HPoint3f begin, const HPoint3f end) const;
inline VoxImage<T> clipImage(const float density) const;
inline VoxImage<T> clipImage(const float densityMin,
const float densityMax) const;
inline VoxImage<T> maskImage(const HPoint3f begin, const HPoint3f end,
float value) const;
inline VoxImage<T> maskImage(const float threshold, float belowValue = 0,
float aboveValue = 0) const;
inline VoxImage<T> fixVoxels(const float threshold, float tolerance) const;
inline VoxImage<T> fixVoxels(const float threshold, float tolerance,
const HPoint3f begin, const HPoint3f end) const;
inline VoxImage<T> fixVoxelsAroundPlane(const float threshold,
float tolerance, const HPoint3f begin,
const HPoint3f end,
bool aboveAir) const;
inline VoxImage<T> fixVoxels(const HPoint3f begin, const HPoint3f end) const;
inline VoxImage<T> Abs() const;
inline void SelectScalarfComponent(T &element, Scalarf *scalar);
inline void InitVoxels(T t);
// MATH OPERATORS //
inline void operator*=(Scalarf scalar) {
for (unsigned int i = 0; i < m_Data.size(); ++i)
m_Data[i].Value *= scalar;
}
inline void operator+=(Scalarf scalar) {
for (unsigned int i = 0; i < m_Data.size(); ++i)
m_Data[i].Value += scalar;
}
inline void operator/=(Scalarf scalar) {
for (unsigned int i = 0; i < m_Data.size(); ++i)
m_Data[i].Value /= scalar;
}
inline void operator-=(Scalarf scalar) {
for (unsigned int i = 0; i < m_Data.size(); ++i)
m_Data[i].Value -= scalar;
}
// MATH VoxImage Operators //
template <typename S> void operator+=(VoxImage<S> &sibling) {
if (this->GetDims() != sibling.GetDims()) {
// printf("Warning when adding VoxImages: I'm NOT doing it!\n");
return;
} // WARNING! You must Warn the user!
for (unsigned int i = 0; i < m_Data.size(); ++i) {
m_Data[i].Value += sibling.At(i).Value;
} }
}
inline std::vector<T> & Data() { return this->m_Data; } template <typename S> void operator-=(VoxImage<S> &sibling) {
inline const std::vector<T>& ConstData() const { return m_Data; } if (this->GetDims() != sibling.GetDims()) {
// printf("Warning when subtracting VoxImages: I'm NOT doing it!\n");
inline const T& At(int i) const { return m_Data.at(i); } return;
inline const T& At(const Vector3i &id) const { return m_Data.at(Map(id)); } } // WARNING! You must Warn the user!
inline T& operator[](unsigned int i) { return m_Data[i]; } for (unsigned int i = 0; i < m_Data.size(); ++i) {
inline T& operator[](const Vector3i &id) { return m_Data[Map(id)]; } m_Data[i].Value -= sibling.At(i).Value;
// this implements Abstract interface //
inline Scalarf GetValue(const Vector3i &id) const {
return this->At(id).Value;
}
inline Scalarf GetValue(const int id) const {
return this->At(id).Value;
} }
}
inline void SetValue(const Vector3i &id, Scalarf value) { template <typename S> void operator*=(VoxImage<S> &sibling) {
this->operator [](id).Value = value; if (this->GetDims() != sibling.GetDims()) {
} // printf("Warning when multiplying VoxImages: I'm NOT doing it!\n");
inline void SetValue(const int id, float value) { return;
this->operator [](id).Value = value; } // WARNING! You must Warn the user!
for (unsigned int i = 0; i < m_Data.size(); ++i) {
m_Data[i].Value *= sibling.At(i).Value;
} }
}
inline void SetDims(const Vector3i &size) { template <typename S> void operator/=(VoxImage<S> &sibling) {
this->m_Data.resize(size.prod()); if (this->GetDims() != sibling.GetDims()) {
BaseClass::BaseClass::SetDims(size); // FIX horrible coding style ! // printf("Warning when dividing VoxImages: I'm NOT doing it!\n");
} return;
} // WARNING! You must Warn the user!
inline VoxImage<T> clipImage(const Vector3i begin, const Vector3i end) const; for (unsigned int i = 0; i < m_Data.size(); ++i) {
inline VoxImage<T> clipImage(const HPoint3f begin, const HPoint3f end) const; m_Data[i].Value /= sibling.At(i).Value;
inline VoxImage<T> clipImage(const float density) const;
inline VoxImage<T> clipImage(const float densityMin, const float densityMax) const;
inline VoxImage<T> maskImage(const HPoint3f begin, const HPoint3f end, float value) const;
inline VoxImage<T> maskImage(const float threshold, float belowValue=0, float aboveValue=0) const;
inline VoxImage<T> fixVoxels(const float threshold, float tolerance) const;
inline VoxImage<T> fixVoxels(const float threshold, float tolerance, const HPoint3f begin, const HPoint3f end) const;
inline VoxImage<T> fixVoxelsAroundPlane(const float threshold, float tolerance, const HPoint3f begin, const HPoint3f end, bool aboveAir) const;
inline VoxImage<T> fixVoxels(const HPoint3f begin, const HPoint3f end) const;
inline VoxImage<T> Abs() const;
inline void SelectScalarfComponent(T &element, Scalarf *scalar);
inline void InitVoxels(T t);
// MATH OPERATORS //
inline void operator *=(Scalarf scalar) {
for(unsigned int i = 0; i < m_Data.size(); ++i)
m_Data[i].Value *= scalar;
}
inline void operator +=(Scalarf scalar) {
for(unsigned int i = 0; i < m_Data.size(); ++i)
m_Data[i].Value += scalar;
}
inline void operator /=(Scalarf scalar) {
for(unsigned int i = 0; i < m_Data.size(); ++i)
m_Data[i].Value /= scalar;
}
inline void operator -=(Scalarf scalar) {
for(unsigned int i = 0; i < m_Data.size(); ++i)
m_Data[i].Value -= scalar;
}
// MATH VoxImage Operators //
template <typename S>
void operator +=(VoxImage<S> &sibling) {
if (this->GetDims() != sibling.GetDims()) {
//printf("Warning when adding VoxImages: I'm NOT doing it!\n");
return;
}// WARNING! You must Warn the user!
for(unsigned int i = 0; i < m_Data.size(); ++i) {
m_Data[i].Value += sibling.At(i).Value;
}
}
template <typename S>
void operator -=(VoxImage<S> &sibling) {
if (this->GetDims() != sibling.GetDims()) {
//printf("Warning when subtracting VoxImages: I'm NOT doing it!\n");
return;
}// WARNING! You must Warn the user!
for(unsigned int i = 0; i < m_Data.size(); ++i) {
m_Data[i].Value -= sibling.At(i).Value;
}
}
template <typename S>
void operator *=(VoxImage<S> &sibling) {
if (this->GetDims() != sibling.GetDims()) {
//printf("Warning when multiplying VoxImages: I'm NOT doing it!\n");
return;
}// WARNING! You must Warn the user!
for(unsigned int i = 0; i < m_Data.size(); ++i) {
m_Data[i].Value *= sibling.At(i).Value;
}
}
template <typename S>
void operator /=(VoxImage<S> &sibling) {
if (this->GetDims() != sibling.GetDims()) {
//printf("Warning when dividing VoxImages: I'm NOT doing it!\n");
return;
}// WARNING! You must Warn the user!
for(unsigned int i = 0; i < m_Data.size(); ++i) {
m_Data[i].Value /= sibling.At(i).Value;
}
} }
}
private: private:
std::vector<T> m_Data; DataAllocator<T> m_Data;
}; };
template<typename T>
VoxImage<T>::VoxImage() :
m_Data(0),
BaseClass(Vector3i(0,0,0))
{ Interface::IsA <T,Interface::Voxel>(); /* structural check for T */ }
template<typename T>
VoxImage<T>::VoxImage(const Vector3i &size) :
m_Data(size.prod()),
BaseClass(size)
{ Interface::IsA <T,Interface::Voxel>(); /* structural check for T */ }
template <typename T> template <typename T>
VoxImage<T> VoxImage<T>::clipImage(const Vector3i begin, const Vector3i end) const VoxImage<T>::VoxImage() : m_Data(0), BaseClass(Vector3i(0, 0, 0)) {
{ Interface::IsA<T, Interface::Voxel>(); /* structural check for T */
Vector3i dim = (end-begin)+Vector3i(1,1,1);
VoxImage<T> out(*this);
out.SetDims(dim);
out.SetPosition(this->GetPosition() + this->GetSpacing().cwiseProduct(begin.cast<float>()) );
for(uint x = 0; x<dim(0); ++x )
for(uint y = 0; y<dim(1); ++y )
for(uint z = 0; z<dim(2); ++z )
{
Vector3i id = Vector3i(x,y,z);
out[id] = this->At(begin + id);
}
return out;
} }
template <typename T> template <typename T>
VoxImage<T> VoxImage<T>::clipImage(const HPoint3f begin, const HPoint3f end) const VoxImage<T>::VoxImage(const Vector3i &size)
{ : m_Data(size.prod()), BaseClass(size) {
Vector3i v1 = this->Find(begin); Interface::IsA<T, Interface::Voxel>(); /* structural check for T */
Vector3i v2 = this->Find(end);
return this->clipImage(v1,v2);
} }
template <typename T> template <typename T>
VoxImage<T> VoxImage<T>::clipImage(const float density) const VoxImage<T> VoxImage<T>::clipImage(const Vector3i begin,
{ const Vector3i end) const {
Vector3i v1 = this->GetDims(); Vector3i dim = (end - begin) + Vector3i(1, 1, 1);
Vector3i v2 = Vector3i(0,0,0); VoxImage<T> out(*this);
for(uint i=0; i< this->m_Data.size(); ++i) { out.SetDims(dim);
if( this->GetValue(i) >= density ) { out.SetPosition(this->GetPosition() +
Vector3i id = this->UnMap(i); this->GetSpacing().cwiseProduct(begin.cast<float>()));
v1 = v1.array().min(id.array());
v2 = v2.array().max(id.array()); for (uint x = 0; x < dim(0); ++x)
} for (uint y = 0; y < dim(1); ++y)
for (uint z = 0; z < dim(2); ++z) {
Vector3i id = Vector3i(x, y, z);
out[id] = this->At(begin + id);
}
return out;
}
template <typename T>
VoxImage<T> VoxImage<T>::clipImage(const HPoint3f begin,
const HPoint3f end) const {
Vector3i v1 = this->Find(begin);
Vector3i v2 = this->Find(end);
return this->clipImage(v1, v2);
}
template <typename T>
VoxImage<T> VoxImage<T>::clipImage(const float density) const {
Vector3i v1 = this->GetDims();
Vector3i v2 = Vector3i(0, 0, 0);
for (uint i = 0; i < this->m_Data.size(); ++i) {
if (this->GetValue(i) >= density) {
Vector3i id = this->UnMap(i);
v1 = v1.array().min(id.array());
v2 = v2.array().max(id.array());
} }
return this->clipImage(v1,v2); }
return this->clipImage(v1, v2);
} }
template <typename T> template <typename T>
VoxImage<T> VoxImage<T>::clipImage(const float densityMin, const float densityMax) const VoxImage<T> VoxImage<T>::clipImage(const float densityMin,
{ const float densityMax) const {
Vector3i v1 = this->GetDims(); Vector3i v1 = this->GetDims();
Vector3i v2 = Vector3i(0,0,0); Vector3i v2 = Vector3i(0, 0, 0);
for(uint i=0; i< this->m_Data.size(); ++i) { for (uint i = 0; i < this->m_Data.size(); ++i) {
if( this->GetValue(i) >= densityMin && this->GetValue(i) <= densityMax) { if (this->GetValue(i) >= densityMin && this->GetValue(i) <= densityMax) {
Vector3i id = this->UnMap(i); Vector3i id = this->UnMap(i);
v1 = v1.array().min(id.array()); v1 = v1.array().min(id.array());
v2 = v2.array().max(id.array()); v2 = v2.array().max(id.array());
}
} }
return this->clipImage(v1,v2); }
return this->clipImage(v1, v2);
} }
template <typename T> template <typename T>
VoxImage<T> VoxImage<T>::maskImage(const HPoint3f begin, const HPoint3f end, float value) const VoxImage<T> VoxImage<T>::maskImage(const HPoint3f begin, const HPoint3f end,
{ float value) const {
VoxImage<T> out(*this); VoxImage<T> out(*this);
out.SetDims(this->GetDims()); out.SetDims(this->GetDims());
out.SetPosition(this->GetPosition()); out.SetPosition(this->GetPosition());
Vector3i voxB = this->Find(begin); Vector3i voxB = this->Find(begin);
Vector3i voxE = this->Find(end); Vector3i voxE = this->Find(end);
Vector3i ID; Vector3i ID;
for(int ix=voxB(0); ix<voxE(0); ix++) for (int ix = voxB(0); ix < voxE(0); ix++)
for(int iy=voxB(1); iy<voxE(1); iy++) for (int iy = voxB(1); iy < voxE(1); iy++)
for(int iz=voxB(2); iz<voxE(2); iz++){ for (int iz = voxB(2); iz < voxE(2); iz++) {
ID << ix,iy,iz; ID << ix, iy, iz;
out.SetValue(ID,value*1.E-6); out.SetValue(ID, value * 1.E-6);
} }
return out; return out;
} }
template <typename T> template <typename T>
VoxImage<T> VoxImage<T>::maskImage(const float threshold, float belowValue, float aboveValue) const VoxImage<T> VoxImage<T>::maskImage(const float threshold, float belowValue,
{ float aboveValue) const {
std::cout << "VoxImage: maskImage, fixing voxels under threshold " << threshold; std::cout << "VoxImage: maskImage, fixing voxels under threshold "
if(belowValue) << threshold;
std::cout << " at value " << belowValue; if (belowValue)
else std::cout << " at value " << belowValue;
std::cout << " at -value"; else
std::cout << ", voxels above threshold at value "; std::cout << " at -value";
if(aboveValue) std::cout << ", voxels above threshold at value ";
std::cout << aboveValue; if (aboveValue)
else std::cout << aboveValue;
std::cout << "found"; else
std::cout << "found";
VoxImage<T> out(*this);
out.SetDims(this->GetDims());
out.SetPosition(this->GetPosition());
VoxImage<T> out(*this); for (uint i = 0; i < this->m_Data.size(); ++i) {
out.SetDims(this->GetDims()); // skip negative voxels: they are already frozen
out.SetPosition(this->GetPosition()); if (this->GetValue(i) >= 0) {
// voxels under threshold
for(uint i=0; i< this->m_Data.size(); ++i) { if (this->GetValue(i) <= threshold * 1.E-6) {
// skip negative voxels: they are already frozen if (belowValue) {
if( this->GetValue(i) >= 0 ){ // std::cout << "vox " << i << ", " <<
// voxels under threshold // this->GetValue(i); std::cout << " ----> set to " <<
if( this->GetValue(i) <= threshold*1.E-6 ){ // -1.*belowValue*1.E-6 << std::endl;
if(belowValue){ out.SetValue(i, -1. * belowValue * 1.E-6);
// std::cout << "vox " << i << ", " << this->GetValue(i); } else
// std::cout << " ----> set to " << -1.*belowValue*1.E-6 << std::endl; out.SetValue(i, -1. * this->GetValue(i));
out.SetValue(i,-1.*belowValue*1.E-6);} }
else // voxels over threshold
out.SetValue(i,-1.*this->GetValue(i)); else {
} if (aboveValue)
// voxels over threshold out.SetValue(i, aboveValue * 1.E-6);
else{ else
if(aboveValue) out.SetValue(i, this->GetValue(i));
out.SetValue(i,aboveValue*1.E-6); }
else
out.SetValue(i,this->GetValue(i));
}
}
} }
return out; }
return out;
} }
template <typename T> template <typename T>
VoxImage<T> VoxImage<T>::fixVoxels(const float threshold, float tolerance) const VoxImage<T> VoxImage<T>::fixVoxels(const float threshold,
{ float tolerance) const {
std::cout << "VoxImage: fixing voxels with value " << threshold << std::endl; std::cout << "VoxImage: fixing voxels with value " << threshold << std::endl;
VoxImage<T> out(*this); VoxImage<T> out(*this);
out.SetDims(this->GetDims()); out.SetDims(this->GetDims());
out.SetPosition(this->GetPosition()); out.SetPosition(this->GetPosition());
for(uint i=0; i< this->m_Data.size(); ++i) { for (uint i = 0; i < this->m_Data.size(); ++i) {
// voxels around threshold
if (fabs(this->GetValue(i) - threshold * 1.E-6) < tolerance * 1.E-6) {
// std::cout << "vox " << i << ", " << this->GetValue(i);
// std::cout << " ----> set to " << -1.*this->GetValue(i) <<
// std::endl;
out.SetValue(i, -1. * this->GetValue(i));
}
}
return out;
}
template <typename T> VoxImage<T> VoxImage<T>::Abs() const {
std::cout << "VoxImage: set abs voxels value " << std::endl;
VoxImage<T> out(*this);
out.SetDims(this->GetDims());
out.SetPosition(this->GetPosition());
for (uint i = 0; i < this->m_Data.size(); ++i)
out.SetValue(i, fabs(this->GetValue(i)));
return out;
}
template <typename T>
VoxImage<T> VoxImage<T>::fixVoxels(const float threshold, float tolerance,
const HPoint3f begin,
const HPoint3f end) const {
VoxImage<T> out(*this);
out.SetDims(this->GetDims());
out.SetPosition(this->GetPosition());
Vector3i voxB = this->Find(begin);
Vector3i voxE = this->Find(end);
Vector3i ID;
for (int ix = voxB(0); ix < voxE(0); ix++)
for (int iy = voxB(1); iy < voxE(1); iy++)
for (int iz = voxB(2); iz < voxE(2); iz++) {
ID << ix, iy, iz;
// voxels around threshold // voxels around threshold
if( fabs(this->GetValue(i) - threshold*1.E-6) < tolerance* 1.E-6 ){ if (fabs(this->GetValue(ID) - threshold * 1.E-6) < tolerance * 1.E-6) {
// std::cout << "vox " << i << ", " << this->GetValue(i); out.SetValue(ID, -1. * this->GetValue(ID));
// std::cout << " ----> set to " << -1.*this->GetValue(i) << std::endl;
out.SetValue(i,-1.*this->GetValue(i));
} }
} }
return out;
return out;
} }
template <typename T> template <typename T>
VoxImage<T> VoxImage<T>::Abs() const VoxImage<T> VoxImage<T>::fixVoxels(const HPoint3f begin,
{ const HPoint3f end) const {
std::cout << "VoxImage: set abs voxels value " << std::endl; VoxImage<T> out(*this);
out.SetDims(this->GetDims());
out.SetPosition(this->GetPosition());
VoxImage<T> out(*this); Vector3i voxB = this->Find(begin);
out.SetDims(this->GetDims()); Vector3i voxE = this->Find(end);
out.SetPosition(this->GetPosition());
for(uint i=0; i< this->m_Data.size(); ++i) Vector3i ID;
out.SetValue(i,fabs(this->GetValue(i)));
return out; for (int ix = voxB(0); ix < voxE(0); ix++)
for (int iy = voxB(1); iy < voxE(1); iy++)
for (int iz = voxB(2); iz < voxE(2); iz++) {
ID << ix, iy, iz;
// voxels around threshold
out.SetValue(ID, -1. * this->GetValue(ID));
}
return out;
} }
template <typename T> template <typename T>
VoxImage<T> VoxImage<T>::fixVoxels( const float threshold, float tolerance, const HPoint3f begin, const HPoint3f end) const VoxImage<T> VoxImage<T>::fixVoxelsAroundPlane(const float threshold,
{ float tolerance, const HPoint3f B,
VoxImage<T> out(*this); const HPoint3f E,
out.SetDims(this->GetDims()); bool aboveAir) const {
out.SetPosition(this->GetPosition()); VoxImage<T> out(*this);
Vector3i dim = this->GetDims();
out.SetDims(dim);
out.SetPosition(this->GetPosition());
Vector3i voxB = this->Find(begin); HPoint3f Bcoll = this->GetPosition().homogeneous();
Vector3i voxE = this->Find(end);
Vector3i ID; Vector3i ID;
for (int ix = 0; ix < dim(0); ix++)
for (int iy = 0; iy < dim(1); iy++)
for (int iz = 0; iz < dim(2); iz++) {
ID << ix, iy, iz;
for(int ix=voxB(0); ix<voxE(0); ix++) // B, E voxel position
for(int iy=voxB(1); iy<voxE(1); iy++) Vector3i iv(ix, iy, iz);
for(int iz=voxB(2); iz<voxE(2); iz++){ Vector3f v =
ID << ix,iy,iz; Vector3f(iv.cast<float>().cwiseProduct(this->GetSpacing()));
// voxels around threshold HPoint3f Bvox = Bcoll + HPoint3f(v);
if( fabs(this->GetValue(ID) - threshold*1.E-6) < tolerance*1.E-6 ){ HPoint3f Evox = Bvox + this->GetSpacing().homogeneous();
out.SetValue(ID,-1.*this->GetValue(ID)); HPoint3f V = Bvox + 0.5 * (this->GetSpacing().homogeneous());
}
}
return out; // if distance point (x0,y0) from line by points (x1,y1) and (x2,y2) is
// less than tolerance
float x1 = B[1];
float y1 = B[2];
float x2 = E[1];
float y2 = E[2];
float x0 = V[1];
float y0 = V[2];
float dist = fabs((x2 - x1) * (y1 - y0) - ((x1 - x0) * (y2 - y1))) /
sqrt((x2 - x1) * (x2 - x1) + ((y2 - y1) * (y2 - y1)));
float distSign = (x2 - x1) * (y1 - y0) - ((x1 - x0) * (y2 - y1));
// set voxel air value
if (dist < tolerance) {
// std::cout << "voxel " << iv << ", line " << dist << ", tolerance "
// << tolerance << std::endl;
out.SetValue(ID, threshold * 1.E-6);
} else
out.SetValue(ID, this->GetValue(ID));
if ((distSign > 0 && aboveAir) || (distSign < 0 && !aboveAir))
out.SetValue(ID, threshold * 1.E-6);
}
return out;
} }
template <typename T> template <typename T> void VoxImage<T>::InitVoxels(T t) {
VoxImage<T> VoxImage<T>::fixVoxels(const HPoint3f begin, const HPoint3f end) const std::fill(m_Data.begin(), m_Data.end(), t); // warning... stl function //
{
VoxImage<T> out(*this);
out.SetDims(this->GetDims());
out.SetPosition(this->GetPosition());
Vector3i voxB = this->Find(begin);
Vector3i voxE = this->Find(end);
Vector3i ID;
for(int ix=voxB(0); ix<voxE(0); ix++)
for(int iy=voxB(1); iy<voxE(1); iy++)
for(int iz=voxB(2); iz<voxE(2); iz++){
ID << ix,iy,iz;
// voxels around threshold
out.SetValue(ID,-1.*this->GetValue(ID));
}
return out;
} }
} // namespace uLib
template <typename T>
VoxImage<T> VoxImage<T>::fixVoxelsAroundPlane( const float threshold, float tolerance, const HPoint3f B, const HPoint3f E, bool aboveAir) const
{
VoxImage<T> out(*this);
Vector3i dim = this->GetDims();
out.SetDims(dim);
out.SetPosition(this->GetPosition());
HPoint3f Bcoll = this->GetPosition().homogeneous();
Vector3i ID;
for(int ix=0; ix<dim(0); ix++)
for(int iy=0; iy<dim(1); iy++)
for(int iz=0; iz<dim(2); iz++){
ID << ix,iy,iz;
// B, E voxel position
Vector3i iv(ix,iy,iz);
Vector3f v = Vector3f(iv.cast<float>().cwiseProduct(this->GetSpacing()));
HPoint3f Bvox = Bcoll + HPoint3f(v);
HPoint3f Evox = Bvox + this->GetSpacing().homogeneous();
HPoint3f V = Bvox + 0.5*(this->GetSpacing().homogeneous());
// if distance point (x0,y0) from line by points (x1,y1) and (x2,y2) is less than tolerance
float x1 = B[1];
float y1 = B[2];
float x2 = E[1];
float y2 = E[2];
float x0 = V[1];
float y0 = V[2];
float dist = fabs( (x2-x1)*(y1-y0) - ((x1-x0)*(y2-y1))) / sqrt( (x2-x1)*(x2-x1)+((y2-y1)*(y2-y1)));
float distSign = (x2-x1)*(y1-y0) - ((x1-x0)*(y2-y1));
// set voxel air value
if(dist < tolerance){
//std::cout << "voxel " << iv << ", line " << dist << ", tolerance " << tolerance << std::endl;
out.SetValue(ID,threshold*1.E-6);
}
else
out.SetValue(ID,this->GetValue(ID));
if((distSign>0 && aboveAir) || (distSign<0 && !aboveAir) )
out.SetValue(ID,threshold*1.E-6);
}
return out;
}
template<typename T>
void VoxImage<T>::InitVoxels(T t)
{
std::fill( m_Data.begin(), m_Data.end(), t ); // warning... stl function //
}
}
#endif // VOXIMAGE_H #endif // VOXIMAGE_H

View File

@@ -23,8 +23,6 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef VOXIMAGEFILTER_H #ifndef VOXIMAGEFILTER_H
#define VOXIMAGEFILTER_H #define VOXIMAGEFILTER_H
@@ -33,96 +31,83 @@
#include "Math/VoxImage.h" #include "Math/VoxImage.h"
namespace uLib { namespace uLib {
namespace Interface { namespace Interface {
struct VoxImageFilterShape { struct VoxImageFilterShape {
template <class Self> void check_structural() { template <class Self> void check_structural() {
uLibCheckFunction(Self,operator(),float,float); uLibCheckFunction(Self, operator(), float, float);
uLibCheckFunction(Self,operator(),float,const Vector3f&); uLibCheckFunction(Self, operator(), float, const Vector3f &);
} }
}; };
} } // namespace Interface
template < typename VoxelT > class Kernel;
template <typename VoxelT> class Kernel;
namespace Abstract { namespace Abstract {
class VoxImageFilter { class VoxImageFilter {
public: public:
virtual void Run() = 0; virtual void Run() = 0;
virtual void SetImage(Abstract::VoxImage *image) = 0; virtual void SetImage(Abstract::VoxImage *image) = 0;
protected: protected:
virtual ~VoxImageFilter() {} virtual ~VoxImageFilter() {}
}; };
} } // namespace Abstract
template <typename VoxelT, typename AlgorithmT>
template < typename VoxelT, typename AlgorithmT > class VoxImageFilter : public Abstract::VoxImageFilter {
class VoxImageFilter : public Abstract::VoxImageFilter
{
public: public:
VoxImageFilter(const Vector3i &size); VoxImageFilter(const Vector3i &size);
void Run(); void Run();
void SetKernelNumericXZY(const std::vector<float> &numeric); void SetKernelNumericXZY(const std::vector<float> &numeric);
void SetKernelSpherical(float (*shape)(float)); void SetKernelSpherical(float (*shape)(float));
template < class ShapeT > template <class ShapeT> void SetKernelSpherical(ShapeT shape);
void SetKernelSpherical( ShapeT shape );
void SetKernelWeightFunction(float (*shape)(const Vector3f &)); void SetKernelWeightFunction(float (*shape)(const Vector3f &));
template < class ShapeT > template <class ShapeT> void SetKernelWeightFunction(ShapeT shape);
void SetKernelWeightFunction( ShapeT shape );
inline Kernel<VoxelT> GetKernelData() const { return this->m_KernelData; } inline const Kernel<VoxelT> &GetKernelData() const {
return this->m_KernelData;
}
inline Kernel<VoxelT> &GetKernelData() { return this->m_KernelData; }
inline VoxImage<VoxelT>* GetImage() const { return this->m_Image; } inline VoxImage<VoxelT> *GetImage() const { return this->m_Image; }
void SetImage(Abstract::VoxImage *image); void SetImage(Abstract::VoxImage *image);
protected: protected:
float Convolve(const VoxImage<VoxelT> &buffer, int index); // remove //
float Convolve(const VoxImage<VoxelT> &buffer, int index); // remove // void SetKernelOffset();
void SetKernelOffset(); float Distance2(const Vector3i &v);
float Distance2(const Vector3i &v); // protected members for algorithm access //
Kernel<VoxelT> m_KernelData;
// protected members for algorithm access // VoxImage<VoxelT> *m_Image;
Kernel<VoxelT> m_KernelData;
VoxImage<VoxelT> *m_Image;
private: private:
AlgorithmT *t_Algoritm; AlgorithmT *t_Algoritm;
}; };
} // namespace uLib
}
#endif // VOXIMAGEFILTER_H #endif // VOXIMAGEFILTER_H
#include "VoxImageFilter.hpp" #include "VoxImageFilter.hpp"
#include "VoxImageFilterLinear.hpp" #include "VoxImageFilter2ndStat.hpp"
#include "VoxImageFilterThreshold.hpp"
#include "VoxImageFilterMedian.hpp"
#include "VoxImageFilterABTrim.hpp" #include "VoxImageFilterABTrim.hpp"
#include "VoxImageFilterBilateral.hpp" #include "VoxImageFilterBilateral.hpp"
#include "VoxImageFilter2ndStat.hpp"
#include "VoxImageFilterCustom.hpp" #include "VoxImageFilterCustom.hpp"
#include "VoxImageFilterLinear.hpp"
#include "VoxImageFilterMedian.hpp"
#include "VoxImageFilterThreshold.hpp"

View File

@@ -23,280 +23,238 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef VOXIMAGEFILTER_HPP #ifndef VOXIMAGEFILTER_HPP
#define VOXIMAGEFILTER_HPP #define VOXIMAGEFILTER_HPP
#include <Math/Dense.h>
#include "Math/StructuredData.h" #include "Math/StructuredData.h"
#include "Math/VoxImage.h" #include "Math/VoxImage.h"
#include "VoxImageFilter.h" #include "VoxImageFilter.h"
#include <Math/Dense.h>
namespace uLib { namespace uLib {
// KERNEL ////////////////////////////////////////////////////////////////////// // KERNEL //////////////////////////////////////////////////////////////////////
template < typename T > template <typename T> class Kernel : public StructuredData {
class Kernel : public StructuredData { typedef StructuredData BaseClass;
typedef StructuredData BaseClass;
public: public:
Kernel(const Vector3i &size); Kernel(const Vector3i &size);
inline T& operator[](const Vector3i &id) { return m_Data[Map(id)]; } inline T &operator[](const Vector3i &id) { return m_Data[Map(id)]; }
inline T& operator[](const int &id) { return m_Data[id]; } inline T &operator[](const int &id) { return m_Data[id]; }
inline int GetCenterData() const; inline int GetCenterData() const;
inline std::vector<T> & Data() { return this->m_Data; } inline DataAllocator<T> &Data() { return this->m_Data; }
inline const std::vector<T>& ConstData() const { return this->m_Data; } inline const DataAllocator<T> &ConstData() const { return this->m_Data; }
void PrintSelf(std::ostream &o) const; void PrintSelf(std::ostream &o) const;
private: private:
std::vector<T> m_Data; DataAllocator<T> m_Data;
}; };
template < typename T > template <typename T>
Kernel<T>::Kernel(const Vector3i &size) : Kernel<T>::Kernel(const Vector3i &size) : BaseClass(size), m_Data(size.prod()) {
BaseClass(size), Interface::IsA<T, Interface::Voxel>();
m_Data(size.prod())
{
Interface::IsA<T,Interface::Voxel>();
} }
template < typename T > template <typename T> inline int Kernel<T>::GetCenterData() const {
inline int Kernel<T>::GetCenterData() const static int center = Map(this->GetDims() / 2);
{ return center;
static int center = Map(this->GetDims() / 2);
return center;
} }
template < typename T > template <typename T> void Kernel<T>::PrintSelf(std::ostream &o) const {
void Kernel<T>::PrintSelf(std::ostream &o) const o << " Filter Kernel Dump [XZ_Y]: \n";
{ Vector3i index;
o << " Filter Kernel Dump [XZ_Y]: \n"; o << "\n Value: \n\n"
Vector3i index; << "------------------------------------------------- \n";
o << "\n Value: \n\n" for (int y = 0; y < this->GetDims()(1); ++y) {
<< "------------------------------------------------- \n"; o << "[y=" << y << "]\n";
for (int y = 0 ; y < this->GetDims()(1); ++y ) { for (int z = 0; z < this->GetDims()(2); ++z) {
o << "[y=" << y << "]\n"; for (int x = 0; x < this->GetDims()(0); ++x) {
for (int z = 0 ; z < this->GetDims()(2); ++z ) { index << x, y, z;
for (int x = 0 ; x < this->GetDims()(0); ++x ) { o << m_Data[Map(index)].Value << " ";
index << x,y,z; }
o << m_Data[Map(index)].Value << " "; o << "\n";
} o << "\n";
} o << " --------------------------------------------------- \n";
} }
o << "\n Offset: \n" o << " --------------------------------------------------- \n";
<< "------------------------------------------------- \n"; }
for (int y = 0 ; y < this->GetDims()(1); ++y ) { o << "\n Offset: \n"
o << "[y=" << y << "]\n"; << "------------------------------------------------- \n";
for (int z = 0 ; z < this->GetDims()(2); ++z ) { for (int y = 0; y < this->GetDims()(1); ++y) {
for (int x = 0 ; x < this->GetDims()(0); ++x ) { o << "[y=" << y << "]\n";
index << x,y,z; for (int z = 0; z < this->GetDims()(2); ++z) {
o << m_Data[Map(index)].Count << " "; for (int x = 0; x < this->GetDims()(0); ++x) {
} o << "\n"; index << x, y, z;
} o << " --------------------------------------------------- \n"; o << m_Data[Map(index)].Count << " ";
}
o << "\n";
} }
o << " --------------------------------------------------- \n";
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#define _TPL_ template <typename VoxelT, typename AlgorithmT>
#define _TPLT_ VoxelT, AlgorithmT
#define _TPL_ template < typename VoxelT , typename AlgorithmT >
#define _TPLT_ VoxelT,AlgorithmT
_TPL_ _TPL_
VoxImageFilter<_TPLT_>::VoxImageFilter(const Vector3i &size) : VoxImageFilter<_TPLT_>::VoxImageFilter(const Vector3i &size)
m_KernelData(size), : m_KernelData(size), t_Algoritm(static_cast<AlgorithmT *>(this)) {}
t_Algoritm(static_cast<AlgorithmT *>(this))
{
_TPL_
void VoxImageFilter<_TPLT_>::Run() {
VoxImage<VoxelT> buffer = *m_Image;
#pragma omp parallel for
for (int i = 0; i < m_Image->Data().size(); ++i)
m_Image->operator[](i).Value = this->t_Algoritm->Evaluate(buffer, i);
#pragma omp barrier
} }
_TPL_ _TPL_
void VoxImageFilter<_TPLT_>::Run() void VoxImageFilter<_TPLT_>::SetKernelOffset() {
{ Vector3i id(0, 0, 0);
VoxImage<VoxelT> buffer = *m_Image; for (int z = 0; z < m_KernelData.GetDims()(2); ++z) {
#pragma omp parallel for for (int x = 0; x < m_KernelData.GetDims()(0); ++x) {
for(int i=0 ; i < m_Image->Data().size() ; ++i) for (int y = 0; y < m_KernelData.GetDims()(1); ++y) {
m_Image->operator [](i).Value = this->t_Algoritm->Evaluate(buffer,i); id << x, y, z;
#pragma omp barrier m_KernelData[id].Count = id.transpose() * m_Image->GetIncrements();
} }
_TPL_
void VoxImageFilter<_TPLT_>::SetKernelOffset()
{
Vector3i id(0,0,0);
for( int z=0 ; z < m_KernelData.GetDims()(2); ++z ) {
for( int x=0 ; x < m_KernelData.GetDims()(0); ++x ) {
for( int y=0 ; y < m_KernelData.GetDims()(1); ++y ) {
id << x,y,z;
m_KernelData[id].Count = id.transpose() * m_Image->GetIncrements();
}
}
} }
}
} }
_TPL_ _TPL_
float VoxImageFilter<_TPLT_>::Distance2(const Vector3i &v) float VoxImageFilter<_TPLT_>::Distance2(const Vector3i &v) {
{ Vector3i tmp = v;
Vector3i tmp = v; const Vector3i &dim = this->m_KernelData.GetDims();
const Vector3i &dim = this->m_KernelData.GetDims(); Vector3i center = dim / 2;
Vector3i center = dim / 2; tmp = tmp - center;
tmp = tmp - center; center = center.cwiseProduct(center);
center = center.cwiseProduct(center); tmp = tmp.cwiseProduct(tmp);
tmp = tmp.cwiseProduct(tmp); return (float)(tmp.sum()) /
return (float)(tmp.sum()) / (float)( center.sum() + 0.25 * (float)(center.sum() +
(3 - (dim(0) % 2) - (dim(1) % 2) - (dim(2) % 2))); 0.25 * (3 - (dim(0) % 2) - (dim(1) % 2) - (dim(2) % 2)));
} }
_TPL_ _TPL_
void VoxImageFilter<_TPLT_>::SetKernelNumericXZY(const std::vector<float> &numeric) void VoxImageFilter<_TPLT_>::SetKernelNumericXZY(
{ const std::vector<float> &numeric) {
// set data order // // set data order //
StructuredData::Order order = m_KernelData.GetDataOrder(); StructuredData::Order order = m_KernelData.GetDataOrder();
//m_KernelData.SetDataOrder(StructuredData::XZY); // m_KernelData.SetDataOrder(StructuredData::XZY);
Vector3i id; Vector3i id;
int index = 0; int index = 0;
for( int y=0 ; y < m_KernelData.GetDims()(1); ++y ) { for (int y = 0; y < m_KernelData.GetDims()(1); ++y) {
for( int z=0 ; z < m_KernelData.GetDims()(2); ++z ) { for (int z = 0; z < m_KernelData.GetDims()(2); ++z) {
for( int x=0 ; x < m_KernelData.GetDims()(0); ++x ) { for (int x = 0; x < m_KernelData.GetDims()(0); ++x) {
id << x,y,z; id << x, y, z;
m_KernelData[id].Value = numeric[index++]; m_KernelData[id].Value = numeric[index++];
} }
}
} }
//m_KernelData.SetDataOrder(order); }
// m_KernelData.SetDataOrder(order);
} }
_TPL_ _TPL_
void VoxImageFilter<_TPLT_>::SetKernelSpherical(float(* shape)(float)) void VoxImageFilter<_TPLT_>::SetKernelSpherical(float (*shape)(float)) {
{ Vector3i id;
Vector3i id; for (int y = 0; y < m_KernelData.GetDims()(1); ++y) {
for( int y=0 ; y < m_KernelData.GetDims()(1); ++y ) { for (int z = 0; z < m_KernelData.GetDims()(2); ++z) {
for( int z=0 ; z < m_KernelData.GetDims()(2); ++z ) { for (int x = 0; x < m_KernelData.GetDims()(0); ++x) {
for( int x=0 ; x < m_KernelData.GetDims()(0); ++x ) { id << x, y, z;
id << x,y,z; m_KernelData[id].Value = shape(this->Distance2(id));
m_KernelData[id].Value = shape(this->Distance2(id)); }
}
}
} }
}
} }
_TPL_ template <class ShapeT> _TPL_ template <class ShapeT>
void VoxImageFilter<_TPLT_>::SetKernelSpherical(ShapeT shape) void VoxImageFilter<_TPLT_>::SetKernelSpherical(ShapeT shape) {
{ Interface::IsA<ShapeT, Interface::VoxImageFilterShape>();
Interface::IsA<ShapeT,Interface::VoxImageFilterShape>(); Vector3i id;
Vector3i id; for (int y = 0; y < m_KernelData.GetDims()(1); ++y) {
for( int y=0 ; y < m_KernelData.GetDims()(1); ++y ) { for (int z = 0; z < m_KernelData.GetDims()(2); ++z) {
for( int z=0 ; z < m_KernelData.GetDims()(2); ++z ) { for (int x = 0; x < m_KernelData.GetDims()(0); ++x) {
for( int x=0 ; x < m_KernelData.GetDims()(0); ++x ) { id << x, y, z;
id << x,y,z; m_KernelData[id].Value = shape(this->Distance2(id));
m_KernelData[id].Value = shape(this->Distance2(id)); }
}
}
} }
}
} }
_TPL_ _TPL_
void VoxImageFilter<_TPLT_>::SetKernelWeightFunction(float (*shape)(const Vector3f &)) void VoxImageFilter<_TPLT_>::SetKernelWeightFunction(
{ float (*shape)(const Vector3f &)) {
const Vector3i &dim = m_KernelData.GetDims(); const Vector3i &dim = m_KernelData.GetDims();
Vector3i id; Vector3i id;
Vector3f pt; Vector3f pt;
for( int y=0 ; y < dim(1); ++y ) { for (int y = 0; y < dim(1); ++y) {
for( int z=0 ; z < dim(2); ++z ) { for (int z = 0; z < dim(2); ++z) {
for( int x=0 ; x < dim(0); ++x ) { for (int x = 0; x < dim(0); ++x) {
// get voxels centroid coords from kernel center // // get voxels centroid coords from kernel center //
id << x,y,z; id << x, y, z;
pt << id(0) - dim(0)/2 + 0.5 * !(dim(0) % 2), pt << id(0) - dim(0) / 2 + 0.5 * !(dim(0) % 2),
id(1) - dim(1)/2 + 0.5 * !(dim(1) % 2), id(1) - dim(1) / 2 + 0.5 * !(dim(1) % 2),
id(2) - dim(2)/2 + 0.5 * !(dim(2) % 2); id(2) - dim(2) / 2 + 0.5 * !(dim(2) % 2);
// compute function using given shape // // compute function using given shape //
m_KernelData[id].Value = shape(pt); m_KernelData[id].Value = shape(pt);
} }
}
} }
}
} }
_TPL_ template < class ShapeT > _TPL_ template <class ShapeT>
void VoxImageFilter<_TPLT_>::SetKernelWeightFunction(ShapeT shape) void VoxImageFilter<_TPLT_>::SetKernelWeightFunction(ShapeT shape) {
{ Interface::IsA<ShapeT, Interface::VoxImageFilterShape>();
Interface::IsA<ShapeT,Interface::VoxImageFilterShape>(); const Vector3i &dim = m_KernelData.GetDims();
const Vector3i &dim = m_KernelData.GetDims(); Vector3i id;
Vector3i id; Vector3f pt;
Vector3f pt; for (int y = 0; y < dim(1); ++y) {
for( int y=0 ; y < dim(1); ++y ) { for (int z = 0; z < dim(2); ++z) {
for( int z=0 ; z < dim(2); ++z ) { for (int x = 0; x < dim(0); ++x) {
for( int x=0 ; x < dim(0); ++x ) { // get voxels centroid coords from kernel center //
// get voxels centroid coords from kernel center // id << x, y, z;
id << x,y,z; pt << id(0) - dim(0) / 2 + 0.5 * !(dim(0) % 2),
pt << id(0) - dim(0)/2 + 0.5 * !(dim(0) % 2), id(1) - dim(1) / 2 + 0.5 * !(dim(1) % 2),
id(1) - dim(1)/2 + 0.5 * !(dim(1) % 2), id(2) - dim(2) / 2 + 0.5 * !(dim(2) % 2);
id(2) - dim(2)/2 + 0.5 * !(dim(2) % 2); // compute function using given shape //
// compute function using given shape // m_KernelData[id].Value = shape(pt);
m_KernelData[id].Value = shape(pt); }
}
}
} }
}
} }
_TPL_ _TPL_
void VoxImageFilter<_TPLT_>::SetImage(Abstract::VoxImage *image) void VoxImageFilter<_TPLT_>::SetImage(Abstract::VoxImage *image) {
{ this->m_Image = reinterpret_cast<VoxImage<VoxelT> *>(image);
this->m_Image = reinterpret_cast<VoxImage<VoxelT> *> (image); this->SetKernelOffset();
this->SetKernelOffset();
} }
_TPL_ _TPL_
float VoxImageFilter<_TPLT_>::Convolve(const VoxImage<VoxelT> &buffer, int index) float VoxImageFilter<_TPLT_>::Convolve(const VoxImage<VoxelT> &buffer,
{ int index) {
const std::vector<VoxelT> &vbuf = buffer.ConstData(); const DataAllocator<VoxelT> &vbuf = buffer.ConstData();
const std::vector<VoxelT> &vker = m_KernelData.ConstData(); const DataAllocator<VoxelT> &vker = m_KernelData.ConstData();
int vox_size = vbuf.size(); int vox_size = vbuf.size();
int ker_size = vker.size(); int ker_size = vker.size();
int pos; int pos;
float conv = 0, ksum = 0; float conv = 0, ksum = 0;
for (int ik = 0; ik < ker_size; ++ik) { for (int ik = 0; ik < ker_size; ++ik) {
pos = index + vker[ik].Count - vker[m_KernelData.GetCenterData()].Count; pos = index + vker[ik].Count - vker[m_KernelData.GetCenterData()].Count;
pos = (pos + vox_size) % vox_size; pos = (pos + vox_size) % vox_size;
conv += vbuf[pos].Value * vker[ik].Value; conv += vbuf[pos].Value * vker[ik].Value;
ksum += vker[ik].Value; ksum += vker[ik].Value;
} }
return conv / ksum; return conv / ksum;
} }
#undef _TPLT_ #undef _TPLT_
#undef _TPL_ #undef _TPL_
} // namespace uLib
}
#endif // VOXIMAGEFILTER_HPP #endif // VOXIMAGEFILTER_HPP

View File

@@ -23,14 +23,12 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef VOXIMAGEFILTER2NDSTAT_HPP #ifndef VOXIMAGEFILTER2NDSTAT_HPP
#define VOXIMAGEFILTER2NDSTAT_HPP #define VOXIMAGEFILTER2NDSTAT_HPP
#include <Math/Dense.h>
#include "Math/VoxImage.h" #include "Math/VoxImage.h"
#include "VoxImageFilter.h" #include "VoxImageFilter.h"
#include <Math/Dense.h>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
///// VOXIMAGE FILTER ABTRIM ///////////////////////////////////////////////// ///// VOXIMAGE FILTER ABTRIM /////////////////////////////////////////////////
@@ -39,45 +37,42 @@
namespace uLib { namespace uLib {
template <typename VoxelT> template <typename VoxelT>
class VoxFilterAlgorithm2ndStat : class VoxFilterAlgorithm2ndStat
public VoxImageFilter<VoxelT, VoxFilterAlgorithm2ndStat<VoxelT> > { : public VoxImageFilter<VoxelT, VoxFilterAlgorithm2ndStat<VoxelT>> {
public: public:
typedef VoxImageFilter<VoxelT, VoxFilterAlgorithm2ndStat<VoxelT> > BaseClass; typedef VoxImageFilter<VoxelT, VoxFilterAlgorithm2ndStat<VoxelT>> BaseClass;
VoxFilterAlgorithm2ndStat(const Vector3i &size) : VoxFilterAlgorithm2ndStat(const Vector3i &size) : BaseClass(size) {}
BaseClass(size)
{ }
float Evaluate(const VoxImage<VoxelT> &buffer, int index) float Evaluate(const VoxImage<VoxelT> &buffer, int index) {
{ const DataAllocator<VoxelT> &vbuf = buffer.ConstData();
const std::vector<VoxelT> &vbuf = buffer.ConstData(); const DataAllocator<VoxelT> &vker = this->m_KernelData.ConstData();
const std::vector<VoxelT> &vker = this->m_KernelData.ConstData(); int vox_size = vbuf.size();
int vox_size = vbuf.size(); int ker_size = vker.size();
int ker_size = vker.size(); int pos;
int pos;
// mean // // mean //
float conv = 0, ksum = 0; float conv = 0, ksum = 0;
for (int ik = 0; ik < ker_size; ++ik) { for (int ik = 0; ik < ker_size; ++ik) {
pos = index + vker[ik].Count - vker[this->m_KernelData.GetCenterData()].Count; pos = index + vker[ik].Count -
pos = (pos + vox_size) % vox_size; vker[this->m_KernelData.GetCenterData()].Count;
conv += vbuf[pos].Value * vker[ik].Value; pos = (pos + vox_size) % vox_size;
ksum += vker[ik].Value; conv += vbuf[pos].Value * vker[ik].Value;
} ksum += vker[ik].Value;
float mean = conv / ksum;
// rms //
conv = 0;
for (int ik = 0; ik < ker_size; ++ik) {
pos = index + vker[ik].Count - vker[this->m_KernelData.GetCenterData()].Count;
pos = (pos + vox_size) % vox_size;
conv += pow((vbuf[pos].Value * vker[ik].Value) - mean , 2);
}
return conv / (vker.size() - 1) ;
} }
float mean = conv / ksum;
// rms //
conv = 0;
for (int ik = 0; ik < ker_size; ++ik) {
pos = index + vker[ik].Count -
vker[this->m_KernelData.GetCenterData()].Count;
pos = (pos + vox_size) % vox_size;
conv += pow((vbuf[pos].Value * vker[ik].Value) - mean, 2);
}
return conv / (vker.size() - 1);
}
}; };
} } // namespace uLib
#endif // VOXIMAGEFILTER2NDSTAT_HPP #endif // VOXIMAGEFILTER2NDSTAT_HPP

View File

@@ -23,14 +23,12 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef VOXIMAGEFILTERABTRIM_HPP #ifndef VOXIMAGEFILTERABTRIM_HPP
#define VOXIMAGEFILTERABTRIM_HPP #define VOXIMAGEFILTERABTRIM_HPP
#include <Math/Dense.h>
#include "Math/VoxImage.h" #include "Math/VoxImage.h"
#include "VoxImageFilter.h" #include "VoxImageFilter.h"
#include <Math/Dense.h>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
///// VOXIMAGE FILTER ABTRIM ///////////////////////////////////////////////// ///// VOXIMAGE FILTER ABTRIM /////////////////////////////////////////////////
@@ -38,142 +36,257 @@
namespace uLib { namespace uLib {
#if defined(USE_CUDA) && defined(__CUDACC__)
template <typename VoxelT> template <typename VoxelT>
class VoxFilterAlgorithmAbtrim : __global__ void ABTrimFilterKernel(const VoxelT *in, VoxelT *out,
public VoxImageFilter<VoxelT, VoxFilterAlgorithmAbtrim<VoxelT> > { const VoxelT *kernel, int vox_size,
int ker_size, int center_count, int mAtrim,
int mBtrim) {
int index = blockIdx.x * blockDim.x + threadIdx.x;
if (index < vox_size) {
// Allocate space for sorting
extern __shared__ char shared_mem[];
VoxelT *mfh =
(VoxelT *)&shared_mem[threadIdx.x * ker_size * sizeof(VoxelT)];
struct KernelSortAscending for (int i = 0; i < ker_size; ++i) {
{ mfh[i].Count = i;
bool operator()(const VoxelT& e1, const VoxelT& e2) }
{ return e1.Value < e2.Value; }
}; for (int ik = 0; ik < ker_size; ik++) {
int pos = index + kernel[ik].Count - center_count;
if (pos < 0) {
pos += vox_size * ((-pos / vox_size) + 1);
}
pos = pos % vox_size;
mfh[ik].Value = in[pos].Value;
}
// Simple bubble sort for small arrays
for (int i = 0; i < ker_size - 1; i++) {
for (int j = 0; j < ker_size - i - 1; j++) {
if (mfh[j].Value > mfh[j + 1].Value) {
VoxelT temp = mfh[j];
mfh[j] = mfh[j + 1];
mfh[j + 1] = temp;
}
}
}
float ker_sum = 0;
float fconv = 0;
for (int ik = 0; ik < mAtrim; ik++) {
ker_sum += kernel[mfh[ik].Count].Value;
}
for (int ik = mAtrim; ik < ker_size - mBtrim; ik++) {
fconv += mfh[ik].Value * kernel[mfh[ik].Count].Value;
ker_sum += kernel[mfh[ik].Count].Value;
}
for (int ik = ker_size - mBtrim; ik < ker_size; ik++) {
ker_sum += kernel[mfh[ik].Count].Value;
}
out[index].Value = fconv / ker_sum;
}
}
#endif
template <typename VoxelT>
class VoxFilterAlgorithmAbtrim
: public VoxImageFilter<VoxelT, VoxFilterAlgorithmAbtrim<VoxelT>> {
struct KernelSortAscending {
bool operator()(const VoxelT &e1, const VoxelT &e2) {
return e1.Value < e2.Value;
}
};
public: public:
typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmAbtrim<VoxelT> > BaseClass; typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmAbtrim<VoxelT>> BaseClass;
VoxFilterAlgorithmAbtrim(const Vector3i &size) : VoxFilterAlgorithmAbtrim(const Vector3i &size) : BaseClass(size) {
BaseClass(size) mAtrim = 0;
{ mBtrim = 0;
mAtrim = 0; }
mBtrim = 0;
#if defined(USE_CUDA) && defined(__CUDACC__)
void Run() {
if (this->m_Image->Data().GetDevice() == MemoryDevice::VRAM ||
this->m_KernelData.Data().GetDevice() == MemoryDevice::VRAM) {
this->m_Image->Data().MoveToVRAM();
this->m_KernelData.Data().MoveToVRAM();
VoxImage<VoxelT> buffer = *(this->m_Image);
buffer.Data().MoveToVRAM();
int vox_size = buffer.Data().size();
int ker_size = this->m_KernelData.Data().size();
VoxelT *d_img_out = this->m_Image->Data().GetVRAMData();
const VoxelT *d_img_in = buffer.Data().GetVRAMData();
const VoxelT *d_kernel = this->m_KernelData.Data().GetVRAMData();
int center_count =
this->m_KernelData[this->m_KernelData.GetCenterData()].Count;
int threadsPerBlock = 256;
int blocksPerGrid = (vox_size + threadsPerBlock - 1) / threadsPerBlock;
size_t shared_mem_size = threadsPerBlock * ker_size * sizeof(VoxelT);
ABTrimFilterKernel<<<blocksPerGrid, threadsPerBlock, shared_mem_size>>>(
d_img_in, d_img_out, d_kernel, vox_size, ker_size, center_count,
mAtrim, mBtrim);
cudaDeviceSynchronize();
} else {
BaseClass::Run();
}
}
#endif
float Evaluate(const VoxImage<VoxelT> &buffer, int index) {
const DataAllocator<VoxelT> &vbuf = buffer.ConstData();
const DataAllocator<VoxelT> &vker = this->m_KernelData.ConstData();
int vox_size = vbuf.size();
int ker_size = vker.size();
int pos;
std::vector<VoxelT> mfh(ker_size);
for (int i = 0; i < ker_size; ++i)
mfh[i].Count = i; // index key for ordering function
for (int ik = 0; ik < ker_size; ik++) {
pos = index + vker[ik].Count -
vker[this->m_KernelData.GetCenterData()].Count;
pos = (pos + vox_size) % vox_size;
mfh[ik].Value = vbuf[pos].Value;
} }
float Evaluate(const VoxImage<VoxelT> &buffer, int index) std::sort(mfh.begin(), mfh.end(), KernelSortAscending());
{ float ker_sum = 0;
const std::vector<VoxelT> &vbuf = buffer.ConstData(); float fconv = 0;
const std::vector<VoxelT> &vker = this->m_KernelData.ConstData(); for (int ik = 0; ik < mAtrim; ik++)
int vox_size = vbuf.size(); ker_sum += vker[mfh[ik].Count].Value;
int ker_size = vker.size(); for (int ik = mAtrim; ik < ker_size - mBtrim; ik++) {
int pos; fconv += mfh[ik].Value * vker[mfh[ik].Count].Value; // convloution //
ker_sum += vker[mfh[ik].Count].Value;
std::vector<VoxelT> mfh(ker_size);
for (int i = 0; i < ker_size; ++i)
mfh[i].Count = i; //index key for ordering function
for (int ik = 0; ik < ker_size; ik++) {
pos = index + vker[ik].Count - vker[this->m_KernelData.GetCenterData()].Count;
pos = (pos + vox_size) % vox_size;
mfh[ik].Value = vbuf[pos].Value;
}
std::sort(mfh.begin(), mfh.end(), KernelSortAscending());
float ker_sum = 0;
float fconv = 0;
for (int ik = 0; ik < mAtrim; ik++)
ker_sum += vker[ mfh[ik].Count ].Value;
for (int ik = mAtrim; ik < ker_size - mBtrim; ik++) {
fconv += mfh[ik].Value * vker[ mfh[ik].Count ].Value; // convloution //
ker_sum += vker[ mfh[ik].Count ].Value;
}
for (int ik = ker_size - mBtrim; ik < ker_size; ik++)
ker_sum += vker[ mfh[ik].Count ].Value;
return fconv / ker_sum;
} }
for (int ik = ker_size - mBtrim; ik < ker_size; ik++)
ker_sum += vker[mfh[ik].Count].Value;
inline void SetABTrim(int a, int b) { mAtrim = a; mBtrim = b; } return fconv / ker_sum;
}
inline void SetABTrim(int a, int b) {
mAtrim = a;
mBtrim = b;
}
private: private:
int mAtrim; int mAtrim;
int mBtrim; int mBtrim;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Roberspierre Filter // // Roberspierre Filter //
template <typename VoxelT> template <typename VoxelT>
class VoxFilterAlgorithmSPR : class VoxFilterAlgorithmSPR
public VoxImageFilter<VoxelT, VoxFilterAlgorithmSPR<VoxelT> > { : public VoxImageFilter<VoxelT, VoxFilterAlgorithmSPR<VoxelT>> {
struct KernelSortAscending struct KernelSortAscending {
{ bool operator()(const VoxelT &e1, const VoxelT &e2) {
bool operator()(const VoxelT& e1, const VoxelT& e2) return e1.Value < e2.Value;
{ return e1.Value < e2.Value; } }
}; };
public: public:
typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmSPR<VoxelT> > BaseClass; typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmSPR<VoxelT>> BaseClass;
VoxFilterAlgorithmSPR(const Vector3i &size) : VoxFilterAlgorithmSPR(const Vector3i &size) : BaseClass(size) {
BaseClass(size) mAtrim = 0;
{ mBtrim = 0;
mAtrim = 0; }
mBtrim = 0;
#if defined(USE_CUDA) && defined(__CUDACC__)
void Run() {
if (this->m_Image->Data().GetDevice() == MemoryDevice::VRAM ||
this->m_KernelData.Data().GetDevice() == MemoryDevice::VRAM) {
this->m_Image->Data().MoveToVRAM();
this->m_KernelData.Data().MoveToVRAM();
VoxImage<VoxelT> buffer = *(this->m_Image);
buffer.Data().MoveToVRAM();
int vox_size = buffer.Data().size();
int ker_size = this->m_KernelData.Data().size();
VoxelT *d_img_out = this->m_Image->Data().GetVRAMData();
const VoxelT *d_img_in = buffer.Data().GetVRAMData();
const VoxelT *d_kernel = this->m_KernelData.Data().GetVRAMData();
int center_count =
this->m_KernelData[this->m_KernelData.GetCenterData()].Count;
int threadsPerBlock = 256;
int blocksPerGrid = (vox_size + threadsPerBlock - 1) / threadsPerBlock;
size_t shared_mem_size = threadsPerBlock * ker_size * sizeof(VoxelT);
ABTrimFilterKernel<<<blocksPerGrid, threadsPerBlock, shared_mem_size>>>(
d_img_in, d_img_out, d_kernel, vox_size, ker_size, center_count,
mAtrim, mBtrim);
cudaDeviceSynchronize();
} else {
BaseClass::Run();
}
}
#endif
float Evaluate(const VoxImage<VoxelT> &buffer, int index) {
const DataAllocator<VoxelT> &vbuf = buffer.ConstData();
const DataAllocator<VoxelT> &vker = this->m_KernelData.ConstData();
int vox_size = vbuf.size();
int ker_size = vker.size();
int pos;
std::vector<VoxelT> mfh(ker_size);
for (int i = 0; i < ker_size; ++i)
mfh[i].Count = i; // index key for ordering function
for (int ik = 0; ik < ker_size; ik++) {
pos = index + vker[ik].Count -
vker[this->m_KernelData.GetCenterData()].Count;
pos = (pos + vox_size) % vox_size;
mfh[ik].Value = vbuf[pos].Value;
} }
float Evaluate(const VoxImage<VoxelT> &buffer, int index) std::sort(mfh.begin(), mfh.end(), KernelSortAscending());
{ float spr = vbuf[index].Value;
const std::vector<VoxelT> &vbuf = buffer.ConstData(); if ((mAtrim > 0 && spr <= mfh[mAtrim - 1].Value) ||
const std::vector<VoxelT> &vker = this->m_KernelData.ConstData(); (mBtrim > 0 && spr >= mfh[ker_size - mBtrim].Value)) {
int vox_size = vbuf.size(); float ker_sum = 0;
int ker_size = vker.size(); float fconv = 0;
int pos; for (int ik = 0; ik < mAtrim; ik++)
ker_sum += vker[mfh[ik].Count].Value;
for (int ik = mAtrim; ik < ker_size - mBtrim; ik++) {
fconv += mfh[ik].Value * vker[mfh[ik].Count].Value;
ker_sum += vker[mfh[ik].Count].Value;
}
for (int ik = ker_size - mBtrim; ik < ker_size; ik++)
ker_sum += vker[mfh[ik].Count].Value;
std::vector<VoxelT> mfh(ker_size); return fconv / ker_sum;
for (int i = 0; i < ker_size; ++i) } else
mfh[i].Count = i; //index key for ordering function return spr;
for (int ik = 0; ik < ker_size; ik++) { }
pos = index + vker[ik].Count -
vker[this->m_KernelData.GetCenterData()].Count;
pos = (pos + vox_size) % vox_size;
mfh[ik].Value = vbuf[pos].Value;
}
std::sort(mfh.begin(), mfh.end(), KernelSortAscending()); inline void SetABTrim(int a, int b) {
float spr = vbuf[index].Value; mAtrim = a;
if( (mAtrim > 0 && spr <= mfh[mAtrim-1].Value) || mBtrim = b;
(mBtrim > 0 && spr >= mfh[ker_size - mBtrim].Value) ) }
{
float ker_sum = 0;
float fconv = 0;
for (int ik = 0; ik < mAtrim; ik++)
ker_sum += vker[ mfh[ik].Count ].Value;
for (int ik = mAtrim; ik < ker_size - mBtrim; ik++) {
fconv += mfh[ik].Value * vker[ mfh[ik].Count ].Value;
ker_sum += vker[ mfh[ik].Count ].Value;
}
for (int ik = ker_size - mBtrim; ik < ker_size; ik++)
ker_sum += vker[ mfh[ik].Count ].Value;
return fconv / ker_sum;
}
else
return spr;
}
inline void SetABTrim(int a, int b) { mAtrim = a; mBtrim = b; }
private: private:
int mAtrim; int mAtrim;
int mBtrim; int mBtrim;
}; };
} // namespace uLib
}
#endif // VOXIMAGEFILTERABTRIM_HPP #endif // VOXIMAGEFILTERABTRIM_HPP

View File

@@ -23,14 +23,12 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef VOXIMAGEFILTERBILATERAL_HPP #ifndef VOXIMAGEFILTERBILATERAL_HPP
#define VOXIMAGEFILTERBILATERAL_HPP #define VOXIMAGEFILTERBILATERAL_HPP
#include <Math/Dense.h>
#include "Math/VoxImage.h" #include "Math/VoxImage.h"
#include "VoxImageFilter.h" #include "VoxImageFilter.h"
#include <Math/Dense.h>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
///// VOXIMAGE FILTER LINEAR ///////////////////////////////////////////////// ///// VOXIMAGE FILTER LINEAR /////////////////////////////////////////////////
@@ -38,115 +36,119 @@
namespace uLib { namespace uLib {
template <typename VoxelT> template <typename VoxelT>
class VoxFilterAlgorithmBilateral : class VoxFilterAlgorithmBilateral
public VoxImageFilter<VoxelT, VoxFilterAlgorithmBilateral<VoxelT> > { : public VoxImageFilter<VoxelT, VoxFilterAlgorithmBilateral<VoxelT>> {
public: public:
typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmBilateral<VoxelT> > BaseClass; typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmBilateral<VoxelT>> BaseClass;
VoxFilterAlgorithmBilateral(const Vector3i &size) : BaseClass(size) { VoxFilterAlgorithmBilateral(const Vector3i &size) : BaseClass(size) {
m_sigma = 1; m_sigma = 1;
} }
float Evaluate(const VoxImage<VoxelT> &buffer, int index) float Evaluate(const VoxImage<VoxelT> &buffer, int index) {
{ const DataAllocator<VoxelT> &vbuf = buffer.ConstData();
const std::vector<VoxelT> &vbuf = buffer.ConstData(); const DataAllocator<VoxelT> &vker = this->m_KernelData.ConstData();
const std::vector<VoxelT> &vker = this->m_KernelData.ConstData(); int vox_size = vbuf.size();
int vox_size = vbuf.size(); int ker_size = vker.size();
int ker_size = vker.size(); int pos;
int pos; float conv = 0, ksum = 0;
float conv = 0, ksum = 0; float gamma_smooth;
float gamma_smooth; for (int ik = 0; ik < ker_size; ++ik) {
for (int ik = 0; ik < ker_size; ++ik) { // if (ik==this->m_KernelData.GetCenterData()) continue;
// if (ik==this->m_KernelData.GetCenterData()) continue; pos = index + vker[ik].Count -
pos = index + vker[ik].Count - vker[this->m_KernelData.GetCenterData()].Count; vker[this->m_KernelData.GetCenterData()].Count;
pos = (pos + vox_size) % vox_size; pos = (pos + vox_size) % vox_size;
gamma_smooth = compute_gauss( fabs(vbuf[index].Value - vbuf[pos].Value) * 1.E6 ); gamma_smooth =
conv += vbuf[pos].Value * vker[ik].Value * gamma_smooth; compute_gauss(fabs(vbuf[index].Value - vbuf[pos].Value) * 1.E6);
ksum += vker[ik].Value * gamma_smooth; conv += vbuf[pos].Value * vker[ik].Value * gamma_smooth;
} ksum += vker[ik].Value * gamma_smooth;
return conv / ksum;
} }
return conv / ksum;
}
inline void SetIntensitySigma(const float s) { m_sigma = s; } inline void SetIntensitySigma(const float s) { m_sigma = s; }
private: private:
inline float compute_gauss(const float x) { inline float compute_gauss(const float x) {
return 1/(sqrt(2*M_PI)* m_sigma) * exp(-0.5*(x*x)/(m_sigma*m_sigma)); return 1 / (sqrt(2 * M_PI) * m_sigma) *
} exp(-0.5 * (x * x) / (m_sigma * m_sigma));
}
Scalarf m_sigma; Scalarf m_sigma;
}; };
template <typename VoxelT> template <typename VoxelT>
class VoxFilterAlgorithmBilateralTrim : class VoxFilterAlgorithmBilateralTrim
public VoxImageFilter<VoxelT, VoxFilterAlgorithmBilateralTrim<VoxelT> > { : public VoxImageFilter<VoxelT, VoxFilterAlgorithmBilateralTrim<VoxelT>> {
typedef std::pair<float,float> FPair; typedef std::pair<float, float> FPair;
struct KernelSortAscending struct KernelSortAscending {
{ bool operator()(const FPair &e1, const FPair &e2) {
bool operator()(const FPair& e1, const FPair& e2) return e1.second < e2.second;
{ return e1.second < e2.second; } }
}; };
public: public:
typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmBilateralTrim<VoxelT> > BaseClass; typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmBilateralTrim<VoxelT>>
VoxFilterAlgorithmBilateralTrim(const Vector3i &size) : BaseClass(size) { BaseClass;
m_sigma = 1; VoxFilterAlgorithmBilateralTrim(const Vector3i &size) : BaseClass(size) {
mAtrim = 0; m_sigma = 1;
mBtrim = 0; mAtrim = 0;
mBtrim = 0;
}
float Evaluate(const VoxImage<VoxelT> &buffer, int index) {
const DataAllocator<VoxelT> &vbuf = buffer.ConstData();
const DataAllocator<VoxelT> &vker = this->m_KernelData.ConstData();
int img_size = vbuf.size();
int ker_size = vker.size();
int pos;
std::vector<FPair> mfh(ker_size);
for (int i = 0; i < ker_size; ++i)
mfh[i].first = vker[i].Value; // kernel value in first
for (int ik = 0; ik < ker_size; ik++) {
pos = index + vker[ik].Count -
vker[this->m_KernelData.GetCenterData()].Count;
pos = (pos + img_size) % img_size;
mfh[ik].second = vbuf[pos].Value; // image value in second
} }
std::sort(mfh.begin(), mfh.end(), KernelSortAscending());
float Evaluate(const VoxImage<VoxelT> &buffer, int index) float conv = 0, ksum = 0;
{ float gamma_smooth;
const std::vector<VoxelT> &vbuf = buffer.ConstData(); // for (int ik = 0; ik < mAtrim; ik++)
const std::vector<VoxelT> &vker = this->m_KernelData.ConstData(); // ksum += mfh[ik].first;
int img_size = vbuf.size(); for (int ik = mAtrim; ik < ker_size - mBtrim; ik++) {
int ker_size = vker.size(); gamma_smooth =
int pos; compute_gauss(fabs(vbuf[index].Value - mfh[ik].second) * 1.E6);
conv += mfh[ik].first * mfh[ik].second * gamma_smooth;
ksum += mfh[ik].first * gamma_smooth;
std::vector<FPair> mfh(ker_size);
for (int i = 0; i < ker_size; ++i)
mfh[i].first = vker[i].Value; // kernel value in first
for (int ik = 0; ik < ker_size; ik++) {
pos = index + vker[ik].Count - vker[this->m_KernelData.GetCenterData()].Count;
pos = (pos + img_size) % img_size;
mfh[ik].second = vbuf[pos].Value; // image value in second
}
std::sort(mfh.begin(), mfh.end(), KernelSortAscending());
float conv = 0, ksum = 0;
float gamma_smooth;
// for (int ik = 0; ik < mAtrim; ik++)
// ksum += mfh[ik].first;
for (int ik = mAtrim; ik < ker_size - mBtrim; ik++) {
gamma_smooth = compute_gauss( fabs(vbuf[index].Value - mfh[ik].second) * 1.E6 );
conv += mfh[ik].first * mfh[ik].second * gamma_smooth;
ksum += mfh[ik].first * gamma_smooth;
}
// for (int ik = ker_size - mBtrim; ik < ker_size; ik++)
// ksum += mfh[ik].first;
return conv / ksum;
} }
// for (int ik = ker_size - mBtrim; ik < ker_size; ik++)
// ksum += mfh[ik].first;
inline void SetIntensitySigma(const float s) { m_sigma = s; } return conv / ksum;
inline void SetABTrim(int a, int b) { mAtrim = a; mBtrim = b; } }
inline void SetIntensitySigma(const float s) { m_sigma = s; }
inline void SetABTrim(int a, int b) {
mAtrim = a;
mBtrim = b;
}
private: private:
inline float compute_gauss(const float x) { inline float compute_gauss(const float x) {
return 1/(sqrt(2*M_PI)* m_sigma) * exp(-0.5*(x*x)/(m_sigma*m_sigma)); return 1 / (sqrt(2 * M_PI) * m_sigma) *
} exp(-0.5 * (x * x) / (m_sigma * m_sigma));
}
Scalarf m_sigma; Scalarf m_sigma;
int mAtrim; int mAtrim;
int mBtrim; int mBtrim;
}; };
} } // namespace uLib
#endif // VOXIMAGEFILTERBILATERAL_HPP #endif // VOXIMAGEFILTERBILATERAL_HPP

View File

@@ -23,14 +23,12 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef VOXIMAGEFILTERCUSTOM_HPP #ifndef VOXIMAGEFILTERCUSTOM_HPP
#define VOXIMAGEFILTERCUSTOM_HPP #define VOXIMAGEFILTERCUSTOM_HPP
#include <Math/Dense.h>
#include "Math/VoxImage.h" #include "Math/VoxImage.h"
#include "VoxImageFilter.h" #include "VoxImageFilter.h"
#include <Math/Dense.h>
#define likely(expr) __builtin_expect(!!(expr), 1) #define likely(expr) __builtin_expect(!!(expr), 1)
@@ -41,50 +39,50 @@
namespace uLib { namespace uLib {
template <typename VoxelT> template <typename VoxelT>
class VoxFilterAlgorithmCustom : class VoxFilterAlgorithmCustom
public VoxImageFilter<VoxelT, VoxFilterAlgorithmCustom<VoxelT> > { : public VoxImageFilter<VoxelT, VoxFilterAlgorithmCustom<VoxelT>> {
typedef float (*FunctionPt)(const std::vector<Scalarf> &);
typedef float (* FunctionPt)(const std::vector<Scalarf> &);
public: public:
typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmCustom<VoxelT> > BaseClass; typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmCustom<VoxelT>> BaseClass;
VoxFilterAlgorithmCustom(const Vector3i &size) : VoxFilterAlgorithmCustom(const Vector3i &size)
BaseClass(size), m_CustomEvaluate(NULL) : BaseClass(size), m_CustomEvaluate(NULL) {}
{}
float Evaluate(const VoxImage<VoxelT> &buffer, int index) float Evaluate(const VoxImage<VoxelT> &buffer, int index) {
{ if (likely(m_CustomEvaluate)) {
if(likely(m_CustomEvaluate)) { const DataAllocator<VoxelT> &vbuf = buffer.ConstData();
const std::vector<VoxelT> &vbuf = buffer.ConstData(); const DataAllocator<VoxelT> &vker = this->m_KernelData.ConstData();
const std::vector<VoxelT> &vker = this->m_KernelData.ConstData(); int vox_size = vbuf.size();
int vox_size = vbuf.size(); int ker_size = vker.size();
int ker_size = vker.size(); int pos;
int pos;
float ker_sum = 0; float ker_sum = 0;
std::vector<Scalarf> mfh(ker_size); std::vector<Scalarf> mfh(ker_size);
for (int ik = 0; ik < ker_size; ik++) { for (int ik = 0; ik < ker_size; ik++) {
pos = index + vker[ik].Count - vker[this->m_KernelData.GetCenterData()].Count; pos = index + vker[ik].Count -
pos = (pos + vox_size) % vox_size; vker[this->m_KernelData.GetCenterData()].Count;
mfh[ik] = vbuf[pos].Value * vker[ik].Value; pos = (pos + vox_size) % vox_size;
ker_sum += vker[ik].Value; mfh[ik] = vbuf[pos].Value * vker[ik].Value;
} ker_sum += vker[ik].Value;
}
return this->m_CustomEvaluate(mfh);
}
else
std::cerr << "Custom evaluate function is NULL \n" <<
"No operation performed by filter.\n";
return this->m_CustomEvaluate(mfh);
} else {
std::cerr << "Custom evaluate function is NULL \n"
<< "No operation performed by filter.\n";
return 0;
} }
}
inline void SetCustomEvaluate(FunctionPt funPt) { this->m_CustomEvaluate = funPt; } inline void SetCustomEvaluate(FunctionPt funPt) {
this->m_CustomEvaluate = funPt;
}
private: private:
FunctionPt m_CustomEvaluate; FunctionPt m_CustomEvaluate;
}; };
} } // namespace uLib
#endif // VOXIMAGEFILTERCUSTOM_HPP #endif // VOXIMAGEFILTERCUSTOM_HPP

View File

@@ -23,14 +23,12 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef VOXIMAGEFILTERLINEAR_HPP #ifndef VOXIMAGEFILTERLINEAR_HPP
#define VOXIMAGEFILTERLINEAR_HPP #define VOXIMAGEFILTERLINEAR_HPP
#include <Math/Dense.h>
#include "Math/VoxImage.h" #include "Math/VoxImage.h"
#include "VoxImageFilter.h" #include "VoxImageFilter.h"
#include <Math/Dense.h>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
///// VOXIMAGE FILTER LINEAR ///////////////////////////////////////////////// ///// VOXIMAGE FILTER LINEAR /////////////////////////////////////////////////
@@ -38,32 +36,86 @@
namespace uLib { namespace uLib {
#if defined(USE_CUDA) && defined(__CUDACC__)
template <typename VoxelT>
__global__ void LinearFilterKernel(const VoxelT *in, VoxelT *out,
const VoxelT *kernel, int vox_size,
int ker_size, int center_count) {
int index = blockIdx.x * blockDim.x + threadIdx.x;
if (index < vox_size) {
float conv = 0;
float ksum = 0;
for (int ik = 0; ik < ker_size; ++ik) {
int pos = index + kernel[ik].Count - center_count;
if (pos < 0) {
pos += vox_size * ((-pos / vox_size) + 1);
}
pos = pos % vox_size;
conv += in[pos].Value * kernel[ik].Value;
ksum += kernel[ik].Value;
}
out[index].Value = conv / ksum;
}
}
#endif
template <typename VoxelT> template <typename VoxelT>
class VoxFilterAlgorithmLinear : class VoxFilterAlgorithmLinear
public VoxImageFilter<VoxelT, VoxFilterAlgorithmLinear<VoxelT> > { : public VoxImageFilter<VoxelT, VoxFilterAlgorithmLinear<VoxelT>> {
public: public:
typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmLinear<VoxelT> > BaseClass; typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmLinear<VoxelT>> BaseClass;
VoxFilterAlgorithmLinear(const Vector3i &size) : BaseClass(size) {} VoxFilterAlgorithmLinear(const Vector3i &size) : BaseClass(size) {}
float Evaluate(const VoxImage<VoxelT> &buffer, int index) #if defined(USE_CUDA) && defined(__CUDACC__)
{ void Run() {
const std::vector<VoxelT> &vbuf = buffer.ConstData(); if (this->m_Image->Data().GetDevice() == MemoryDevice::VRAM ||
const std::vector<VoxelT> &vker = this->m_KernelData.ConstData(); this->m_KernelData.Data().GetDevice() == MemoryDevice::VRAM) {
int vox_size = vbuf.size();
int ker_size = vker.size(); this->m_Image->Data().MoveToVRAM();
int pos; this->m_KernelData.Data().MoveToVRAM();
float conv = 0, ksum = 0;
for (int ik = 0; ik < ker_size; ++ik) { VoxImage<VoxelT> buffer = *(this->m_Image);
pos = index + vker[ik].Count - vker[this->m_KernelData.GetCenterData()].Count; buffer.Data().MoveToVRAM();
pos = (pos + vox_size) % vox_size;
conv += vbuf[pos].Value * vker[ik].Value; int vox_size = buffer.Data().size();
ksum += vker[ik].Value; int ker_size = this->m_KernelData.Data().size();
}
return conv / ksum; VoxelT *d_img_out = this->m_Image->Data().GetVRAMData();
const VoxelT *d_img_in = buffer.Data().GetVRAMData();
const VoxelT *d_kernel = this->m_KernelData.Data().GetVRAMData();
int center_count =
this->m_KernelData[this->m_KernelData.GetCenterData()].Count;
int threadsPerBlock = 256;
int blocksPerGrid = (vox_size + threadsPerBlock - 1) / threadsPerBlock;
LinearFilterKernel<<<blocksPerGrid, threadsPerBlock>>>(
d_img_in, d_img_out, d_kernel, vox_size, ker_size, center_count);
cudaDeviceSynchronize();
} else {
BaseClass::Run();
} }
}
#endif
float Evaluate(const VoxImage<VoxelT> &buffer, int index) {
const DataAllocator<VoxelT> &vbuf = buffer.ConstData();
const DataAllocator<VoxelT> &vker = this->m_KernelData.ConstData();
int vox_size = vbuf.size();
int ker_size = vker.size();
int pos;
float conv = 0, ksum = 0;
for (int ik = 0; ik < ker_size; ++ik) {
pos = index + vker[ik].Count -
vker[this->m_KernelData.GetCenterData()].Count;
pos = (pos + vox_size) % vox_size;
conv += vbuf[pos].Value * vker[ik].Value;
ksum += vker[ik].Value;
}
return conv / ksum;
}
}; };
} } // namespace uLib
#endif // VOXIMAGEFILTERLINEAR_HPP #endif // VOXIMAGEFILTERLINEAR_HPP

View File

@@ -23,14 +23,12 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef VOXIMAGEFILTERMEDIAN_HPP #ifndef VOXIMAGEFILTERMEDIAN_HPP
#define VOXIMAGEFILTERMEDIAN_HPP #define VOXIMAGEFILTERMEDIAN_HPP
#include <Math/Dense.h>
#include "Math/VoxImage.h" #include "Math/VoxImage.h"
#include "VoxImageFilter.h" #include "VoxImageFilter.h"
#include <Math/Dense.h>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
///// VOXIMAGE FILTER MEDIAN ///////////////////////////////////////////////// ///// VOXIMAGE FILTER MEDIAN /////////////////////////////////////////////////
@@ -39,37 +37,38 @@
namespace uLib { namespace uLib {
template <typename VoxelT> template <typename VoxelT>
class VoxFilterAlgorithmMedian : class VoxFilterAlgorithmMedian
public VoxImageFilter<VoxelT, VoxFilterAlgorithmMedian<VoxelT> > { : public VoxImageFilter<VoxelT, VoxFilterAlgorithmMedian<VoxelT>> {
public: public:
typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmMedian<VoxelT> > BaseClass; typedef VoxImageFilter<VoxelT, VoxFilterAlgorithmMedian<VoxelT>> BaseClass;
VoxFilterAlgorithmMedian(const Vector3i &size) : BaseClass(size) {} VoxFilterAlgorithmMedian(const Vector3i &size) : BaseClass(size) {}
float Evaluate(const VoxImage<VoxelT> &buffer, int index) float Evaluate(const VoxImage<VoxelT> &buffer, int index) {
{ const DataAllocator<VoxelT> &vbuf = buffer.ConstData();
const std::vector<VoxelT> &vbuf = buffer.ConstData(); const DataAllocator<VoxelT> &vker = this->m_KernelData.ConstData();
const std::vector<VoxelT> &vker = this->m_KernelData.ConstData(); int vox_size = vbuf.size();
int vox_size = vbuf.size(); int ker_size = vker.size();
int ker_size = vker.size(); int pos;
int pos;
std::vector<float> mfh(ker_size); std::vector<float> mfh(ker_size);
for (int ik = 0; ik < ker_size; ik++) { for (int ik = 0; ik < ker_size; ik++) {
pos = index + vker[ik].Count - vker[this->m_KernelData.GetCenterData()].Count; pos = index + vker[ik].Count -
pos = (pos + vox_size) % vox_size; vker[this->m_KernelData.GetCenterData()].Count;
mfh[ik] = vbuf[pos].Value * vker[ik].Value; pos = (pos + vox_size) % vox_size;
} mfh[ik] = vbuf[pos].Value * vker[ik].Value;
std::sort(mfh.begin(), mfh.end());
pos = 0;
// count zeroes in filter kernel to move it out of median //
for (int i = 0; i < ker_size; ++i)
if (vker[i].Value == 0.0) pos++;
// median //
pos += (ker_size - pos) / 2;
return mfh[pos];
} }
std::sort(mfh.begin(), mfh.end());
pos = 0;
// count zeroes in filter kernel to move it out of median //
for (int i = 0; i < ker_size; ++i)
if (vker[i].Value == 0.0)
pos++;
// median //
pos += (ker_size - pos) / 2;
return mfh[pos];
}
}; };
} } // namespace uLib
#endif // VOXIMAGEFILTERMEDIAN_HPP #endif // VOXIMAGEFILTERMEDIAN_HPP

View File

@@ -23,11 +23,10 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include <iostream> #include <iostream>
#include "VoxRaytracer.h"
#include "Utils.h" #include "Utils.h"
#include "VoxRaytracer.h"
#define unlikely(expr) __builtin_expect(!!(expr), 0) #define unlikely(expr) __builtin_expect(!!(expr), 0)
@@ -39,215 +38,215 @@ namespace uLib {
///// RAY DATA ///////////////////////////////////////////////////////////////// ///// RAY DATA /////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void VoxRaytracer::RayData::AddElement(Id_t id, float L) void VoxRaytracer::RayData::AddElement(Id_t id, float L) {
{ if (m_Count >= m_Data.size()) {
Element el = {id, L}; size_t new_size = m_Data.size() == 0 ? 128 : m_Data.size() * 2;
m_Data.push_back(el); m_Data.resize(new_size);
m_TotalLength += L; }
Element el = {id, L};
m_Data[m_Count] = el;
m_Count++;
m_TotalLength += L;
} }
void VoxRaytracer::RayData::AppendRay(const VoxRaytracer::RayData &in) {
void VoxRaytracer::RayData::AppendRay(const VoxRaytracer::RayData &in) if (unlikely(in.m_Count == 0)) {
{ std::cout << "Warinig: PoCA on exit border!\n";
if (unlikely(!in.m_Data.size())) { return;
std::cout << "Warinig: PoCA on exit border!\n"; } else if (unlikely(m_Count == 0)) {
return; m_Data.resize(in.m_Count);
for (size_t i = 0; i < in.m_Count; ++i) {
m_Data[i] = in.m_Data[i];
} }
else if (unlikely(!m_Data.size())) { m_Count = in.m_Count;
m_Data = in.m_Data; m_TotalLength = in.m_TotalLength;
std::cout << "Warinig: PoCA on entrance border!\n"; std::cout << "Warinig: PoCA on entrance border!\n";
return; return;
} } else {
else { // Opzione 1) un voxel in piu' //
// Opzione 1) un voxel in piu' // if (in.m_Count > 0) {
m_Data.reserve(m_Data.size() + in.m_Data.size()); if (m_Count + in.m_Count > m_Data.size()) {
m_Data.insert(m_Data.end(), in.m_Data.begin(), in.m_Data.end()); m_Data.resize(m_Count + in.m_Count);
// Opzione 2) merge dei voxel nel poca. }
// RayData::Element &e1 = m_Data.back(); for (size_t i = 0; i < in.m_Count; ++i) {
// const RayData::Element &e2 = in.m_Data.front(); m_Data[m_Count + i] = in.m_Data[i];
// if(e1.vox_id == e2.vox_id) }
// { m_Count += in.m_Count;
// m_Data.reserve(m_Data.size() + in.m_Data.size() - 1);
// e1.L += e2.L; //fix//
// m_Data.insert(m_Data.end(), in.m_Data.begin()+1, in.m_Data.end());
// }
// else {
// m_Data.reserve(m_Data.size() + in.m_Data.size());
// m_Data.insert(m_Data.end(), in.m_Data.begin(), in.m_Data.end());
// }
m_TotalLength += in.m_TotalLength;
} }
m_TotalLength += in.m_TotalLength;
}
} }
void VoxRaytracer::RayData::PrintSelf(std::ostream &o) void VoxRaytracer::RayData::PrintSelf(std::ostream &o) {
{ o << "Ray: total lenght " << m_TotalLength << "\n";
o << "Ray: total lenght " << m_TotalLength << "\n"; for (size_t i = 0; i < m_Count; ++i)
std::vector<Element>::iterator it; o << "[ " << m_Data[i].vox_id << ", " << m_Data[i].L << "] \n";
for(it = m_Data.begin(); it < m_Data.end(); ++it)
o << "[ " << (*it).vox_id << ", " << (*it).L << "] \n";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//// RAY TRACER //////////////////////////////////////////////////////////////// //// RAY TRACER ////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool VoxRaytracer::GetEntryPoint(const HLine3f &line, HPoint3f &pt) {
Vector4f s = m_Image->GetLocalPoint(line.direction);
pt = m_Image->GetLocalPoint(line.origin);
bool VoxRaytracer::GetEntryPoint(const HLine3f &line, HPoint3f &pt) // Considers Structured grid dimensions //
{ Vector4f dims = m_Image->GetDims().homogeneous().cast<float>();
Vector4f s = m_Image->GetLocalPoint(line.direction); pt = pt.cwiseQuotient(dims);
pt = m_Image->GetLocalPoint(line.origin); s = s.cwiseQuotient(dims);
// Considers Structured grid dimensions // float l = s.head(3).norm();
Vector4f dims = m_Image->GetDims().homogeneous().cast<float>(); Vector3f L(l / s(0), l / s(1), l / s(2));
pt = pt.cwiseQuotient(dims);
s = s.cwiseQuotient(dims);
float l = s.head(3).norm(); Vector3f offset;
Vector3f L(l/s(0), l/s(1), l/s(2)); for (int i = 0; i < 3; ++i)
offset(i) = (s(i) > 0) - (pt(i) - floor(pt(i)));
offset = offset.cwiseProduct(L).cwiseAbs();
Vector3f offset; int id;
for(int i=0;i<3;++i) float d;
offset(i) = (s(i)>0) - (pt(i)-floor(pt(i))) ; for (int loop = 0; loop < 8; loop++) {
offset = offset.cwiseProduct(L).cwiseAbs(); int check_border = 0;
for (int i = 0; i < 3; ++i) {
int id; float d; check_border += pt(i) > 1;
for(int loop=0; loop<8; loop++) check_border += pt(i) < 0;
{
int check_border = 0;
for ( int i=0; i<3 ;++i) {
check_border += pt(i) > 1;
check_border += pt(i) < 0;
}
if(check_border == 0) {
for(int i=0;i<3;++i)
pt(i) *= (float)dims(i);
pt = m_Image->GetWorldPoint(pt);
return true;
}
d = offset.minCoeff(&id);
for(int i=0; i<3; ++i)
pt(i) += d / L(i);
pt(id) = rintf(pt(id));
offset.array() -= d;
offset(id) = fabs(L(id));
} }
for(int i=0;i<3;++i) if (check_border == 0) {
for (int i = 0; i < 3; ++i)
pt(i) *= (float)dims(i); pt(i) *= (float)dims(i);
pt = m_Image->GetWorldPoint(pt); pt = m_Image->GetWorldPoint(pt);
return false; return true;
}
bool VoxRaytracer::GetExitPoint(const HLine3f &line, HPoint3f &pt)
{
HLine3f out = line;
out.direction *= -1;
return GetEntryPoint(out,pt);
}
VoxRaytracer::RayData VoxRaytracer::TraceBetweenPoints(const HPoint3f &in,
const HPoint3f &out)
const
{
RayData ray;
Vector4f pt1 = m_Image->GetLocalPoint(in);
Vector4f pt2 = m_Image->GetLocalPoint(out);
Vector4f s = pt2 - pt1;
float l = s.head(3).norm();
Vector3f L(l/s(0), l/s(1), l/s(2));
// Vector3f scale; // FIXXX
// scale << (m_Image->GetWorldMatrix() * Vector4f(1,0,0,0)).norm(),
// (m_Image->GetWorldMatrix() * Vector4f(0,1,0,0)).norm(),
// (m_Image->GetWorldMatrix() * Vector4f(0,0,1,0)).norm();
Vector3f offset;
for(int i=0;i<3;++i) offset(i) = (s(i)>=0) - (pt1(i)-floor(pt1(i))) ;
offset = offset.cwiseProduct(L).cwiseAbs();
L = L.cwiseAbs();
//---- Check if the ray only crosses one voxel
Vector3i vid = m_Image->Find(in);
if(vid == m_Image->Find(out)){
ray.AddElement(m_Image->Map(vid),s.norm());
return ray;
} }
//---- Otherwise, loop until ray is finished d = offset.minCoeff(&id);
int id; float d; for (int i = 0; i < 3; ++i)
while(l>0){ pt(i) += d / L(i);
d = offset.minCoeff(&id); pt(id) = rintf(pt(id));
if(m_Image->IsInsideGrid(vid)){ offset.array() -= d;
ray.AddElement(m_Image->Map(vid), d * m_scale(id) ); offset(id) = fabs(L(id));
} }
for (int i = 0; i < 3; ++i)
pt(i) *= (float)dims(i);
pt = m_Image->GetWorldPoint(pt);
return false;
}
// nan check // bool VoxRaytracer::GetExitPoint(const HLine3f &line, HPoint3f &pt) {
// if(unlikely(!isFinite(d * scale(id)))) { HLine3f out = line;
// std:: cout << "NAN in raytracer\n"; out.direction *= -1;
// exit(1); return GetEntryPoint(out, pt);
// } }
vid(id) += (int)fast_sign(s(id)); VoxRaytracer::RayData
VoxRaytracer::TraceBetweenPoints(const HPoint3f &in,
const HPoint3f &out) const {
RayData ray;
l -= d; // get the local points and the direction vector
offset.array() -= d; // local to image means in the normalized voxel space where the size
offset(id) = fmin(L(id),l); // of the voxel is 1 in all dimensions
} Vector4f pt1 = m_Image->GetLocalPoint(in);
Vector4f pt2 = m_Image->GetLocalPoint(out);
Vector4f s = pt2 - pt1;
// l is the total length of the ray in normalized voxel space
float l = s.head(3).norm();
// L is the length of the ray between two grid lines in grid
Vector3f L(l / s(0), l / s(1), l / s(2));
// Vector3f scale; // TODO: FIX Scaling
// scale << (m_Image->GetWorldMatrix() * Vector4f(1,0,0,0)).norm(),
// (m_Image->GetWorldMatrix() * Vector4f(0,1,0,0)).norm(),
// (m_Image->GetWorldMatrix() * Vector4f(0,0,1,0)).norm();
Vector3f offset;
for (int i = 0; i < 3; ++i)
offset(i) = (s(i) >= 0) - (pt1(i) - floor(pt1(i)));
offset = offset.cwiseProduct(L).cwiseAbs();
L = L.cwiseAbs();
//---- Check if the ray only crosses one voxel
Vector3i vid = m_Image->Find(in);
if (vid == m_Image->Find(out)) {
ray.AddElement(m_Image->Map(vid), s.norm());
return ray; return ray;
}
//---- Otherwise, loop until ray is finished
int id;
float d;
while (l > 0) {
// find which is the minimum of the offsets to the next grid line
// it will be also the actual normalized voxel ray length
d = offset.minCoeff(&id);
// see if the voxel is inside the grid (we are still inside image)
if (m_Image->IsInsideGrid(vid)) {
// add the voxel to the ray with mapping id and length scaled
ray.AddElement(m_Image->Map(vid), d * m_scale(id));
}
// move to the next voxel
vid(id) += (int)fast_sign(s(id));
// update the remaining length
l -= d;
// update the offsets
offset.array() -= d;
offset(id) = fmin(L(id), l);
}
return ray;
} }
// 20150528 SV for absorbed muons // 20150528 SV for absorbed muons
VoxRaytracer::RayData VoxRaytracer::TraceLine(const HLine3f &line) const VoxRaytracer::RayData VoxRaytracer::TraceLine(const HLine3f &line) const {
{ RayData ray;
RayData ray;
Vector4f pt = m_Image->GetLocalPoint(line.origin); Vector4f pt = m_Image->GetLocalPoint(line.origin);
Vector4f s = m_Image->GetLocalPoint(line.direction); Vector4f s = m_Image->GetLocalPoint(line.direction);
float l = s.head(3).norm(); float l = s.head(3).norm();
// intersection between track and grid when spacing is +1 // intersection between track and grid when spacing is +1
Vector3f L(l/s(0), l/s(1), l/s(2)); Vector3f L(l / s(0), l / s(1), l / s(2));
// RayTracer works with a grid of interspace +1 // RayTracer works with a grid of interspace +1
// Vector3f scale; // FIXXX // Vector3f scale; // FIXXX
// scale << (m_Image->GetWorldMatrix() * Vector4f(1,0,0,0)).norm(), // scale << (m_Image->GetWorldMatrix() * Vector4f(1,0,0,0)).norm(),
// (m_Image->GetWorldMatrix() * Vector4f(0,1,0,0)).norm(), // (m_Image->GetWorldMatrix() * Vector4f(0,1,0,0)).norm(),
// (m_Image->GetWorldMatrix() * Vector4f(0,0,1,0)).norm(); // (m_Image->GetWorldMatrix() * Vector4f(0,0,1,0)).norm();
// offset is the fraction of the segment between grid lines when origin is insiede voxel // offset is the fraction of the segment between grid lines when origin is
// cwiseAbs for having positive distances // insiede voxel cwiseAbs for having positive distances
Vector3f offset; Vector3f offset;
for(int i=0;i<3;++i) for (int i = 0; i < 3; ++i)
offset(i) = (s(i)>=0) - (pt(i)-floor(pt(i))); offset(i) = (s(i) >= 0) - (pt(i) - floor(pt(i)));
offset = offset.cwiseProduct(L).cwiseAbs(); offset = offset.cwiseProduct(L).cwiseAbs();
L = L.cwiseAbs(); L = L.cwiseAbs();
int id; float d; int id;
Vector3i vid = m_Image->Find(line.origin); float d;
while(m_Image->IsInsideGrid(vid)) Vector3i vid = m_Image->Find(line.origin);
{ while (m_Image->IsInsideGrid(vid)) {
// minimun coefficient of offset: id is the coordinate, d is the value // minimun coefficient of offset: id is the coordinate, d is the value
// dependig on which grid line horizontal or vertical it is first intercept // dependig on which grid line horizontal or vertical it is first intercept
d = offset.minCoeff(&id); d = offset.minCoeff(&id);
// add Lij to ray // add Lij to ray
ray.AddElement(m_Image->Map(vid), d * m_scale(id) ); ray.AddElement(m_Image->Map(vid), d * m_scale(id));
// move to the next voxel // move to the next voxel
vid(id) += (int)fast_sign(s(id)); vid(id) += (int)fast_sign(s(id));
offset.array() -= d; offset.array() -= d;
offset(id) = L(id); offset(id) = L(id);
} }
return ray; return ray;
} }
} } // namespace uLib

View File

@@ -23,71 +23,101 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#ifndef VOXRAYTRACER_H #ifndef VOXRAYTRACER_H
#define VOXRAYTRACER_H #define VOXRAYTRACER_H
#include <Core/DataAllocator.h>
#include <Core/Vector.h>
#include <math.h> #include <math.h>
#include <vector> #include <vector>
#include "Math/StructuredGrid.h" #include "Math/StructuredGrid.h"
#include "Math/VoxImage.h"
#ifdef USE_CUDA
#include <cuda_runtime.h>
#endif
namespace uLib { namespace uLib {
class VoxRaytracer { class VoxRaytracer {
public: public:
class RayData { class RayData {
public: public:
RayData() : m_TotalLength(0) {} RayData() : m_TotalLength(0), m_Count(0) {}
typedef struct { struct Element {
Id_t vox_id; Id_t vox_id;
Scalarf L; Scalarf L;
} Element; ~Element() {}
inline void AddElement(Id_t id, float L);
void AppendRay ( const RayData &in);
inline const std::vector<Element>& Data() const { return this->m_Data; }
inline const Scalarf& TotalLength() const { return this->m_TotalLength; }
void PrintSelf(std::ostream &o);
private:
std::vector<Element> m_Data;
Scalarf m_TotalLength;
}; };
inline void AddElement(Id_t id, float L);
public: void AppendRay(const RayData &in);
VoxRaytracer(StructuredGrid &image) : m_Image(&image) {
m_scale <<
(m_Image->GetWorldMatrix() * Vector4f(1,0,0,0)).norm(),
(m_Image->GetWorldMatrix() * Vector4f(0,1,0,0)).norm(),
(m_Image->GetWorldMatrix() * Vector4f(0,0,1,0)).norm();
}
bool GetEntryPoint(const HLine3f &line, HPoint3f &pt); inline uLib::Vector<Element> &Data() { return this->m_Data; }
bool GetExitPoint(const HLine3f &line, HPoint3f &pt); inline const uLib::Vector<Element> &Data() const { return this->m_Data; }
RayData TraceBetweenPoints(const HPoint3f &in, const HPoint3f &out) const; inline size_t Count() const { return this->m_Count; }
RayData TraceLine(const HLine3f &line) const; inline const Scalarf &TotalLength() const { return this->m_TotalLength; }
inline StructuredGrid* GetImage() const { return this->m_Image; } inline void SetCount(size_t c) { this->m_Count = c; }
inline void SetTotalLength(Scalarf tl) { this->m_TotalLength = tl; }
void PrintSelf(std::ostream &o);
private:
uLib::Vector<Element> m_Data;
Scalarf m_TotalLength;
size_t m_Count;
};
public:
VoxRaytracer(StructuredGrid &image) : m_Image(&image) {
m_scale << (m_Image->GetWorldMatrix() * Vector4f(1, 0, 0, 0)).norm(),
(m_Image->GetWorldMatrix() * Vector4f(0, 1, 0, 0)).norm(),
(m_Image->GetWorldMatrix() * Vector4f(0, 0, 1, 0)).norm();
}
bool GetEntryPoint(const HLine3f &line, HPoint3f &pt);
bool GetExitPoint(const HLine3f &line, HPoint3f &pt);
RayData TraceBetweenPoints(const HPoint3f &in, const HPoint3f &out) const;
RayData TraceLine(const HLine3f &line) const;
inline StructuredGrid *GetImage() const { return this->m_Image; }
#ifdef USE_CUDA
template <typename VoxelT>
void AccumulateLinesCUDA(const HLine3f *lines, size_t num_lines,
VoxImage<VoxelT> &image);
void TraceLineCUDA(const HLine3f *lines, size_t num_lines, RayData *out_rays,
int max_elements_per_ray = 128,
float *kernel_time_ms = nullptr);
void TraceBetweenPointsCUDA(const HPoint3f *in_pts, const HPoint3f *out_pts,
size_t num_lines, RayData *out_rays,
int max_elements_per_ray = 128,
float *kernel_time_ms = nullptr);
#endif
private: private:
StructuredGrid *m_Image; StructuredGrid *m_Image;
Vector3f m_scale; Vector3f m_scale;
}; };
} } // namespace uLib
#ifdef USE_CUDA
#include "Math/VoxRaytracerCUDA.hpp"
#endif
#endif // VOXRAYTRACER_H #endif // VOXRAYTRACER_H

View File

@@ -0,0 +1,548 @@
#ifndef VOXRAYTRACERCUDA_H
#define VOXRAYTRACERCUDA_H
#ifdef USE_CUDA
#include "Math/VoxImage.h"
#include "Math/VoxRaytracer.h"
#include <cuda_runtime.h>
namespace uLib {
#ifdef __CUDACC__
template <typename VoxelT>
__global__ void
RaytraceAccumulateKernel(const float *lines_data, int num_lines,
VoxelT *d_image, int dim0, int dim1, int dim2,
const float *inv_world_matrix_data, float scale0,
float scale1, float scale2) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx >= num_lines)
return;
const float *line_ptr = &lines_data[idx * 8];
float o_vec[4] = {line_ptr[0], line_ptr[1], line_ptr[2], line_ptr[3]};
float d_vec[4] = {line_ptr[4], line_ptr[5], line_ptr[6], line_ptr[7]};
float pt[4] = {0, 0, 0, 0};
float s[4] = {0, 0, 0, 0};
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
float m_val = inv_world_matrix_data[i + j * 4];
pt[i] += m_val * o_vec[j];
s[i] += m_val * d_vec[j];
}
}
float l = sqrtf(s[0] * s[0] + s[1] * s[1] + s[2] * s[2]);
if (l == 0)
return;
float L[3];
L[0] = l / s[0];
L[1] = l / s[1];
L[2] = l / s[2];
float offset[3];
for (int i = 0; i < 3; ++i) {
float fpt_i = floorf(pt[i]);
offset[i] = (s[i] >= 0) ? (1.0f - (pt[i] - fpt_i)) : (pt[i] - fpt_i);
offset[i] = fabsf(offset[i] * L[i]);
L[i] = fabsf(L[i]);
}
int id;
float d;
int vid[3] = {(int)floorf(pt[0]), (int)floorf(pt[1]), (int)floorf(pt[2])};
float scale_arr[3] = {scale0, scale1, scale2};
while (vid[0] >= 0 && vid[0] < dim0 && vid[1] >= 0 && vid[1] < dim1 &&
vid[2] >= 0 && vid[2] < dim2) {
d = offset[0];
id = 0;
if (offset[1] < d) {
d = offset[1];
id = 1;
}
if (offset[2] < d) {
d = offset[2];
id = 2;
}
float L_intersect = d * scale_arr[id];
size_t vox_index = vid[0] * dim1 * dim2 + vid[1] * dim2 + vid[2];
atomicAdd(&(d_image[vox_index].Value), L_intersect);
float sign_s = (s[id] >= 0) ? 1.0f : -1.0f;
vid[id] += (int)sign_s;
offset[0] -= d;
offset[1] -= d;
offset[2] -= d;
offset[id] = L[id];
}
}
#endif
template <typename VoxelT>
void VoxRaytracer::AccumulateLinesCUDA(const HLine3f *lines, size_t num_lines,
VoxImage<VoxelT> &image) {
if (num_lines == 0)
return;
image.Data().MoveToVRAM();
float *d_lines = nullptr;
size_t lines_size = num_lines * sizeof(HLine3f);
cudaMalloc(&d_lines, lines_size);
cudaMemcpy(d_lines, lines, lines_size, cudaMemcpyHostToDevice);
int threadsPerBlock = 256;
int blocksPerGrid = (num_lines + threadsPerBlock - 1) / threadsPerBlock;
Vector3i dims = image.GetDims();
Matrix4f inv_world_matrix = image.GetWorldMatrix().inverse();
float *d_inv_world;
cudaMalloc(&d_inv_world, 16 * sizeof(float));
cudaMemcpy(d_inv_world, inv_world_matrix.data(), 16 * sizeof(float),
cudaMemcpyHostToDevice);
#ifdef __CUDACC__
RaytraceAccumulateKernel<<<blocksPerGrid, threadsPerBlock>>>(
d_lines, num_lines, image.Data().GetVRAMData(), dims(0), dims(1), dims(2),
d_inv_world, m_scale(0), m_scale(1), m_scale(2));
cudaDeviceSynchronize();
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess) {
std::cerr << "CUDA Error in AccumulateLinesCUDA: "
<< cudaGetErrorString(err) << std::endl;
}
#else
std::cerr << "RaytraceAccumulateKernel requires NVCC!" << std::endl;
#endif
cudaFree(d_lines);
cudaFree(d_inv_world);
}
#ifdef __CUDACC__
__global__ void TraceBetweenPointsKernel(
const float *in_pts_data, const float *out_pts_data, int num_lines,
VoxRaytracer::RayData::Element **d_out_elements, size_t *d_out_counts,
float *d_out_lengths, int max_elements, int dim0, int dim1, int dim2,
const float *inv_world_matrix_data, float scale0, float scale1,
float scale2, int inc0, int inc1, int inc2) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx >= num_lines)
return;
VoxRaytracer::RayData::Element *ray_out = d_out_elements[idx];
size_t count = 0;
float tot_len = 0.0f;
const float *in_ptr = &in_pts_data[idx * 4];
const float *out_ptr = &out_pts_data[idx * 4];
float pt1[4] = {0, 0, 0, 0}, pt2[4] = {0, 0, 0, 0};
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
float m_val = inv_world_matrix_data[i + j * 4];
pt1[i] += m_val * in_ptr[j];
pt2[i] += m_val * out_ptr[j];
}
}
float s[4];
for (int i = 0; i < 4; ++i)
s[i] = pt2[i] - pt1[i];
float l = sqrtf(s[0] * s[0] + s[1] * s[1] + s[2] * s[2]);
if (l == 0) {
d_out_counts[idx] = count;
d_out_lengths[idx] = tot_len;
return;
}
float L[3];
L[0] = fabsf(l / s[0]);
L[1] = fabsf(l / s[1]);
L[2] = fabsf(l / s[2]);
float offset[3];
for (int i = 0; i < 3; ++i) {
float fpt_i = floorf(pt1[i]);
offset[i] = (s[i] >= 0) ? (1.0f - (pt1[i] - fpt_i)) : (pt1[i] - fpt_i);
offset[i] = fabsf(offset[i] * L[i]);
}
int vid[3] = {(int)floorf(pt1[0]), (int)floorf(pt1[1]), (int)floorf(pt1[2])};
int vid_out[3] = {(int)floorf(pt2[0]), (int)floorf(pt2[1]),
(int)floorf(pt2[2])};
float scale_arr[3] = {scale0, scale1, scale2};
if (vid[0] == vid_out[0] && vid[1] == vid_out[1] && vid[2] == vid_out[2]) {
if (vid[0] >= 0 && vid[0] < dim0 && vid[1] >= 0 && vid[1] < dim1 &&
vid[2] >= 0 && vid[2] < dim2) {
if (count < max_elements) {
int map_id = vid[0] * inc0 + vid[1] * inc1 + vid[2] * inc2;
ray_out[count].vox_id = map_id;
ray_out[count].L = l;
tot_len += l;
count++;
}
}
d_out_counts[idx] = count;
d_out_lengths[idx] = tot_len;
return;
}
int id;
float d;
while (l > 0) {
d = offset[0];
id = 0;
if (offset[1] < d) {
d = offset[1];
id = 1;
}
if (offset[2] < d) {
d = offset[2];
id = 2;
}
if (vid[0] >= 0 && vid[0] < dim0 && vid[1] >= 0 && vid[1] < dim1 &&
vid[2] >= 0 && vid[2] < dim2) {
if (count < max_elements) {
int map_id = vid[0] * inc0 + vid[1] * inc1 + vid[2] * inc2;
ray_out[count].vox_id = map_id;
ray_out[count].L = d * scale_arr[id];
tot_len += d * scale_arr[id];
count++;
}
}
float sign_s = (s[id] >= 0) ? 1.0f : -1.0f;
vid[id] += (int)sign_s;
l -= d;
offset[0] -= d;
offset[1] -= d;
offset[2] -= d;
offset[id] = fminf(L[id], l);
}
d_out_counts[idx] = count;
d_out_lengths[idx] = tot_len;
}
__global__ void TraceLineKernel(const float *lines_data, int num_lines,
VoxRaytracer::RayData::Element **d_out_elements,
size_t *d_out_counts, float *d_out_lengths,
int max_elements, int dim0, int dim1, int dim2,
const float *inv_world_matrix_data,
float scale0, float scale1, float scale2,
int inc0, int inc1, int inc2) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx >= num_lines)
return;
VoxRaytracer::RayData::Element *ray_out = d_out_elements[idx];
size_t count = 0;
float tot_len = 0.0f;
const float *line_ptr = &lines_data[idx * 8];
float o_vec[4] = {line_ptr[0], line_ptr[1], line_ptr[2], line_ptr[3]};
float d_vec[4] = {line_ptr[4], line_ptr[5], line_ptr[6], line_ptr[7]};
float pt[4] = {0, 0, 0, 0}, s[4] = {0, 0, 0, 0};
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
float m_val = inv_world_matrix_data[i + j * 4];
pt[i] += m_val * o_vec[j];
s[i] += m_val * d_vec[j];
}
}
float l = sqrtf(s[0] * s[0] + s[1] * s[1] + s[2] * s[2]);
if (l == 0) {
d_out_counts[idx] = count;
d_out_lengths[idx] = tot_len;
return;
}
float L[3];
L[0] = fabsf(l / s[0]);
L[1] = fabsf(l / s[1]);
L[2] = fabsf(l / s[2]);
float offset[3];
for (int i = 0; i < 3; ++i) {
float fpt_i = floorf(pt[i]);
offset[i] = (s[i] >= 0) ? (1.0f - (pt[i] - fpt_i)) : (pt[i] - fpt_i);
offset[i] = fabsf(offset[i] * L[i]);
}
int id;
float d;
int vid[3] = {(int)floorf(pt[0]), (int)floorf(pt[1]), (int)floorf(pt[2])};
float scale_arr[3] = {scale0, scale1, scale2};
while (vid[0] >= 0 && vid[0] < dim0 && vid[1] >= 0 && vid[1] < dim1 &&
vid[2] >= 0 && vid[2] < dim2) {
d = offset[0];
id = 0;
if (offset[1] < d) {
d = offset[1];
id = 1;
}
if (offset[2] < d) {
d = offset[2];
id = 2;
}
if (count < max_elements) {
int map_id = vid[0] * inc0 + vid[1] * inc1 + vid[2] * inc2;
ray_out[count].vox_id = map_id;
ray_out[count].L = d * scale_arr[id];
tot_len += d * scale_arr[id];
count++;
}
float sign_s = (s[id] >= 0) ? 1.0f : -1.0f;
vid[id] += (int)sign_s;
offset[0] -= d;
offset[1] -= d;
offset[2] -= d;
offset[id] = L[id];
}
d_out_counts[idx] = count;
d_out_lengths[idx] = tot_len;
}
#endif // __CUDACC__
inline void VoxRaytracer::TraceLineCUDA(const HLine3f *lines, size_t num_lines,
RayData *out_rays,
int max_elements_per_ray,
float *kernel_time_ms) {
if (num_lines == 0)
return;
float *d_lines = nullptr;
bool alloc_lines = false;
cudaPointerAttributes ptr_attr;
cudaPointerGetAttributes(&ptr_attr, lines);
if (ptr_attr.type == cudaMemoryTypeDevice) {
d_lines = (float *)lines;
} else {
alloc_lines = true;
size_t lines_size = num_lines * sizeof(HLine3f);
cudaMalloc(&d_lines, lines_size);
cudaMemcpy(d_lines, lines, lines_size, cudaMemcpyHostToDevice);
}
std::vector<RayData::Element *> h_out_elements(num_lines);
for (size_t i = 0; i < num_lines; ++i) {
out_rays[i].Data().resize(max_elements_per_ray);
out_rays[i].Data().MoveToVRAM();
h_out_elements[i] = out_rays[i].Data().GetVRAMData();
}
RayData::Element **d_out_elements;
cudaMalloc(&d_out_elements, num_lines * sizeof(RayData::Element *));
cudaMemcpy(d_out_elements, h_out_elements.data(),
num_lines * sizeof(RayData::Element *), cudaMemcpyHostToDevice);
size_t *d_out_counts;
float *d_out_lengths;
cudaMalloc(&d_out_counts, num_lines * sizeof(size_t));
cudaMalloc(&d_out_lengths, num_lines * sizeof(float));
int threadsPerBlock = 256;
int blocksPerGrid = (num_lines + threadsPerBlock - 1) / threadsPerBlock;
Vector3i dims = m_Image->GetDims();
Vector3i incs = m_Image->GetIncrements();
Matrix4f inv_world_matrix = m_Image->GetWorldMatrix().inverse();
float *d_inv_world;
cudaMalloc(&d_inv_world, 16 * sizeof(float));
cudaMemcpy(d_inv_world, inv_world_matrix.data(), 16 * sizeof(float),
cudaMemcpyHostToDevice);
#ifdef __CUDACC__
cudaEvent_t start, stop;
if (kernel_time_ms) {
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start);
}
TraceLineKernel<<<blocksPerGrid, threadsPerBlock>>>(
d_lines, num_lines, d_out_elements, d_out_counts, d_out_lengths,
max_elements_per_ray, dims(0), dims(1), dims(2), d_inv_world, m_scale(0),
m_scale(1), m_scale(2), incs(0), incs(1), incs(2));
if (kernel_time_ms) {
cudaEventRecord(stop);
cudaEventSynchronize(stop);
cudaEventElapsedTime(kernel_time_ms, start, stop);
cudaEventDestroy(start);
cudaEventDestroy(stop);
} else {
cudaDeviceSynchronize();
}
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess) {
std::cerr << "CUDA Error in TraceLineCUDA: " << cudaGetErrorString(err)
<< std::endl;
}
#else
std::cerr << "TraceLineKernel requires NVCC!" << std::endl;
#endif
std::vector<size_t> h_out_counts(num_lines);
std::vector<float> h_out_lengths(num_lines);
cudaMemcpy(h_out_counts.data(), d_out_counts, num_lines * sizeof(size_t),
cudaMemcpyDeviceToHost);
cudaMemcpy(h_out_lengths.data(), d_out_lengths, num_lines * sizeof(float),
cudaMemcpyDeviceToHost);
for (size_t i = 0; i < num_lines; ++i) {
out_rays[i].SetCount(h_out_counts[i]);
out_rays[i].SetTotalLength(h_out_lengths[i]);
}
if (alloc_lines) {
cudaFree(d_lines);
}
cudaFree(d_out_elements);
cudaFree(d_out_counts);
cudaFree(d_out_lengths);
cudaFree(d_inv_world);
}
inline void VoxRaytracer::TraceBetweenPointsCUDA(
const HPoint3f *in_pts, const HPoint3f *out_pts, size_t num_lines,
RayData *out_rays, int max_elements_per_ray, float *kernel_time_ms) {
if (num_lines == 0)
return;
float *d_in_pts = nullptr;
float *d_out_pts = nullptr;
bool alloc_pts = false;
cudaPointerAttributes ptr_attr;
cudaPointerGetAttributes(&ptr_attr, in_pts);
if (ptr_attr.type == cudaMemoryTypeDevice) {
d_in_pts = (float *)in_pts;
d_out_pts = (float *)out_pts;
} else {
alloc_pts = true;
size_t pts_size = num_lines * sizeof(HPoint3f);
cudaMalloc(&d_in_pts, pts_size);
cudaMalloc(&d_out_pts, pts_size);
cudaMemcpy(d_in_pts, in_pts, pts_size, cudaMemcpyHostToDevice);
cudaMemcpy(d_out_pts, out_pts, pts_size, cudaMemcpyHostToDevice);
}
std::vector<RayData::Element *> h_out_elements(num_lines);
for (size_t i = 0; i < num_lines; ++i) {
out_rays[i].Data().resize(max_elements_per_ray);
out_rays[i].Data().MoveToVRAM();
h_out_elements[i] = out_rays[i].Data().GetVRAMData();
}
RayData::Element **d_out_elements;
cudaMalloc(&d_out_elements, num_lines * sizeof(RayData::Element *));
cudaMemcpy(d_out_elements, h_out_elements.data(),
num_lines * sizeof(RayData::Element *), cudaMemcpyHostToDevice);
size_t *d_out_counts;
float *d_out_lengths;
cudaMalloc(&d_out_counts, num_lines * sizeof(size_t));
cudaMalloc(&d_out_lengths, num_lines * sizeof(float));
int threadsPerBlock = 256;
int blocksPerGrid = (num_lines + threadsPerBlock - 1) / threadsPerBlock;
Vector3i dims = m_Image->GetDims();
Vector3i incs = m_Image->GetIncrements();
Matrix4f inv_world_matrix = m_Image->GetWorldMatrix().inverse();
float *d_inv_world;
cudaMalloc(&d_inv_world, 16 * sizeof(float));
cudaMemcpy(d_inv_world, inv_world_matrix.data(), 16 * sizeof(float),
cudaMemcpyHostToDevice);
#ifdef __CUDACC__
cudaEvent_t start, stop;
if (kernel_time_ms) {
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start);
}
TraceBetweenPointsKernel<<<blocksPerGrid, threadsPerBlock>>>(
d_in_pts, d_out_pts, num_lines, d_out_elements, d_out_counts,
d_out_lengths, max_elements_per_ray, dims(0), dims(1), dims(2),
d_inv_world, m_scale(0), m_scale(1), m_scale(2), incs(0), incs(1),
incs(2));
if (kernel_time_ms) {
cudaEventRecord(stop);
cudaEventSynchronize(stop);
cudaEventElapsedTime(kernel_time_ms, start, stop);
cudaEventDestroy(start);
cudaEventDestroy(stop);
} else {
cudaDeviceSynchronize();
}
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess) {
std::cerr << "CUDA Error in TraceBetweenPointsCUDA: "
<< cudaGetErrorString(err) << std::endl;
}
#else
std::cerr << "TraceBetweenPointsKernel requires NVCC!" << std::endl;
#endif
std::vector<size_t> h_out_counts(num_lines);
std::vector<float> h_out_lengths(num_lines);
cudaMemcpy(h_out_counts.data(), d_out_counts, num_lines * sizeof(size_t),
cudaMemcpyDeviceToHost);
cudaMemcpy(h_out_lengths.data(), d_out_lengths, num_lines * sizeof(float),
cudaMemcpyDeviceToHost);
for (size_t i = 0; i < num_lines; ++i) {
out_rays[i].SetCount(h_out_counts[i]);
out_rays[i].SetTotalLength(h_out_lengths[i]);
}
if (alloc_pts) {
cudaFree(d_in_pts);
cudaFree(d_out_pts);
}
cudaFree(d_out_elements);
cudaFree(d_out_counts);
cudaFree(d_out_lengths);
cudaFree(d_inv_world);
}
} // namespace uLib
#endif // USE_CUDA
#endif // VOXRAYTRACERCUDA_H

View File

@@ -23,88 +23,90 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include "Math/Accumulator.h" #include "Math/Accumulator.h"
#include "testing-prototype.h" #include "testing-prototype.h"
#include <TRandom.h> #include <TRandom.h>
#include <iostream>
#include <vector>
// #include <boost/accumulators/framework/accumulator_set.hpp>
//#include <boost/accumulators/framework/accumulator_set.hpp> // #include <boost/accumulators/statistics/count.hpp>
//#include <boost/accumulators/statistics/count.hpp> // #include <boost/accumulators/accumulators.hpp>
//#include <boost/accumulators/accumulators.hpp>
using namespace uLib; using namespace uLib;
int test_ABTrim() { int test_ABTrim() {
Accumulator_ABTrim<float> acc; Accumulator_ABTrim<float> acc;
acc.SetABTrim(1,1); acc.SetABTrim(1, 1);
std::vector<float> v; std::vector<float> v;
for(float tmpf : {1,5,5,5,300}) v.push_back(tmpf); for (float tmpf : {1, 5, 5, 5, 300})
//v << 1,5,5,5,300; v.push_back(tmpf);
// v << 1,5,5,5,300;
for(std::vector<float>::iterator itr=v.begin(); itr<v.end(); itr++) for (std::vector<float>::iterator itr = v.begin(); itr < v.end(); itr++)
acc += *itr; acc += *itr;
// TODO missing operator << // TODO missing operator <<
//std::cout << "Accumulating Trim(1,1) vector: " // std::cout << "Accumulating Trim(1,1) vector: "
// << v << " ... out = " << acc() << "\n"; // << v << " ... out = " << acc() << "\n";
return( acc() == 15.0 );
return (acc() == 15.0);
} }
int test_Mean() { int test_Mean() {
Accumulator_Mean<float> mean; Accumulator_Mean<float> mean;
TRandom rnd; TRandom rnd;
const int c = 10000000; const int c = 10000000;
std::vector<float> v; std::vector<float> v;
v.reserve(c); v.reserve(c);
for(int i=0;i<c;++i) v.push_back( rnd.Gaus(2000,5) ); for (int i = 0; i < c; ++i)
v.push_back(rnd.Gaus(2000, 5));
float m = 0;
for(int i=0;i<c;++i) m += v[i];
m /= c;
std::cout << "simple mean: " << m << "\n";
for(int i=0;i<c;++i) mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
mean.AddPass();
for(int i=0;i<c;++i) mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
mean.AddPass();
for(int i=0;i<c;++i) mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
mean.AddPass();
for(int i=0;i<c;++i) mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
mean.AddPass();
for(int i=0;i<c;++i) mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
mean.AddPass();
for(int i=0;i<c;++i) mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
mean.AddPass();
for(int i=0;i<c;++i) mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
float m = 0;
for (int i = 0; i < c; ++i)
m += v[i];
m /= c;
std::cout << "simple mean: " << m << "\n";
for (int i = 0; i < c; ++i)
mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
mean.AddPass();
for (int i = 0; i < c; ++i)
mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
mean.AddPass();
for (int i = 0; i < c; ++i)
mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
mean.AddPass();
for (int i = 0; i < c; ++i)
mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
mean.AddPass();
for (int i = 0; i < c; ++i)
mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
mean.AddPass();
for (int i = 0; i < c; ++i)
mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
mean.AddPass();
for (int i = 0; i < c; ++i)
mean(v[i]);
std::cout << "mean pass: " << mean() << "\n";
return 1;
} }
int main(void) { int main(void) {
BEGIN_TESTING(Accumulator); BEGIN_TESTING(Accumulator);
//TEST1( test_ABTrim() ); // TEST1( test_ABTrim() );
test_Mean(); test_Mean();
END_TESTING; END_TESTING;
} }

View File

@@ -5,6 +5,7 @@ set(TESTS
ContainerBoxTest ContainerBoxTest
VoxImageTest VoxImageTest
VoxRaytracerTest VoxRaytracerTest
VoxRaytracerTestExtended
StructuredDataTest StructuredDataTest
VoxImageFilterTest VoxImageFilterTest
PolicyTest PolicyTest
@@ -17,6 +18,13 @@ set(TESTS
set(LIBRARIES set(LIBRARIES
${PACKAGE_LIBPREFIX}Core ${PACKAGE_LIBPREFIX}Core
${PACKAGE_LIBPREFIX}Math ${PACKAGE_LIBPREFIX}Math
Boost::serialization
Eigen3::Eigen
) )
uLib_add_tests(${uLib-module}) uLib_add_tests(Math)
if(USE_CUDA)
set_source_files_properties(VoxImageTest.cpp VoxImageCopyTest.cpp VoxImageFilterTest.cpp VoxRaytracerTest.cpp VoxRaytracerTestExtended.cpp PROPERTIES LANGUAGE CUDA)
set_source_files_properties(VoxRaytracerTest.cpp VoxRaytracerTestExtended.cpp PROPERTIES CXX_STANDARD 17 CUDA_STANDARD 17)
endif()

View File

@@ -23,30 +23,25 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include "testing-prototype.h" #include "testing-prototype.h"
#include "Math/TriangleMesh.h" #include "Math/TriangleMesh.h"
#include <iostream>
using namespace uLib; using namespace uLib;
int main() int main() {
{ BEGIN_TESTING(Triangle Mesh);
BEGIN_TESTING(Triangle Mesh);
TriangleMesh mesh; TriangleMesh mesh;
mesh.AddPoint(Vector3f(0,0,0)); mesh.AddPoint(Vector3f(0, 0, 0));
mesh.AddPoint(Vector3f(0,1,0)); mesh.AddPoint(Vector3f(0, 1, 0));
mesh.AddPoint(Vector3f(1,0,0)); mesh.AddPoint(Vector3f(1, 0, 0));
mesh.AddTriangle(Vector3i(0,1,2)); mesh.AddTriangle(Vector3i(0, 1, 2));
mesh.PrintSelf(std::cout);
mesh.PrintSelf(std::cout); END_TESTING;
END_TESTING;
} }

View File

@@ -23,55 +23,44 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include "testing-prototype.h" #include "testing-prototype.h"
#include "Math/VoxImage.h" #include "Math/VoxImage.h"
using namespace uLib; using namespace uLib;
struct TestVoxel { struct TestVoxel {
Scalarf Value; Scalarf Value;
unsigned int Count; unsigned int Count;
}; };
int main() { int main() {
BEGIN_TESTING(Math VoxImage Copy); BEGIN_TESTING(Math VoxImage Copy);
{ {
VoxImage<TestVoxel> img(Vector3i(10,10,10)); VoxImage<TestVoxel> img(Vector3i(10, 10, 10));
TestVoxel zero = {0,0}; TestVoxel zero = {0.f, 0};
img.InitVoxels(zero); img.InitVoxels(zero);
TestVoxel nonzero = {5.552368, 0}; TestVoxel nonzero = {5.552368f, 0};
img[Vector3i(5,1,7)] = nonzero; img[Vector3i(5, 1, 7)] = nonzero;
img[img.Find(HPoint3f(3,3,3))].Value = 5.552369; img[img.Find(HPoint3f(3, 3, 3))].Value = 5.552369;
TEST1( img.GetValue(Vector3i(5,1,7)) == 5.552368f ); TEST1(img.GetValue(Vector3i(5, 1, 7)) == 5.552368f);
img.SetOrigin(Vector3f(4, 5, 6));
img.SetOrigin(Vector3f(4,5,6)); std::cout << "\n";
std::cout << "\n"; img.PrintSelf(std::cout);
img.PrintSelf(std::cout); VoxImage<TestVoxel> img2 = img;
img2.PrintSelf(std::cout);
VoxImage<TestVoxel> img2 = img; TEST1(img.GetOrigin() == img2.GetOrigin());
img2.PrintSelf(std::cout); TEST1(img.GetSpacing() == img2.GetSpacing());
TEST1( img.GetOrigin() == img2.GetOrigin() ); img2 = img;
TEST1( img.GetSpacing() == img2.GetSpacing() ); }
img2 = img; std::cout << "returns " << _fail << "\n";
END_TESTING;
}
std::cout << "returns " << _fail << "\n";
END_TESTING;
} }

View File

@@ -23,128 +23,191 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include "testing-prototype.h"
#include "Math/StructuredGrid.h" #include "Math/StructuredGrid.h"
#include "testing-prototype.h"
#include "Math/VoxImage.h" #include "Math/VoxImage.h"
#include "Math/VoxImageFilter.h" #include "Math/VoxImageFilter.h"
using namespace uLib; using namespace uLib;
struct TestVoxel { struct TestVoxel {
Scalarf Value; Scalarf Value;
unsigned int Count; unsigned int Count;
}; };
float GaussianShape(float d) float GaussianShape(float d) {
{ // normalized manually .. fix //
// normalized manually .. fix // return 4.5 * exp(-d * 4.5);
return 4.5 * exp(-d * 4.5);
} }
class GaussianShapeClass : public Interface::VoxImageFilterShape { class GaussianShapeClass : public Interface::VoxImageFilterShape {
public: public:
GaussianShapeClass(float sigma) : GaussianShapeClass(float sigma) : m_sigma(sigma) {}
m_sigma(sigma)
{}
float operator ()(float d) { float operator()(float d) { return (1 / m_sigma) * exp(-d / m_sigma); }
return (1/m_sigma) * exp(-d/m_sigma);
}
private: private:
float m_sigma; float m_sigma;
}; };
static float MaxInVector(const std::vector<float> &v) {
static float MaxInVector(const std::vector<float> &v) float max = 0;
{ for (int i = 0; i < v.size(); ++i)
float max = 0; if (v.at(i) > max)
for(int i=0; i<v.size(); ++i) max = v.at(i);
if(v.at(i) > max) max = v.at(i); return max;
return max;
} }
int main() {
BEGIN_TESTING(VoxImageFilters);
int main() VoxImage<TestVoxel> image(Vector3i(20, 30, 40));
{ image[Vector3i(10, 10, 10)].Value = 1;
BEGIN_TESTING(VoxImageFilters); // image[Vector3i(10,10,8)].Value = 1;
image.ExportToVtk("test_filter_original.vtk", 0);
VoxImage<TestVoxel> image(Vector3i(20,30,40)); ////////////////////////////////////////////////////////////////////////////
image[Vector3i(10,10,10)].Value = 1; ////////////////////////////////////////////////////////////////////////////
//image[Vector3i(10,10,8)].Value = 1; ////////////////////////////////////////////////////////////////////////////
image.ExportToVtk("test_filter_original.vtk",0); // RPS //
{
VoxFilterAlgorithmSPR<TestVoxel> filter(Vector3i(2, 3, 4));
VoxImage<TestVoxel> filtered = image;
//////////////////////////////////////////////////////////////////////////// std::vector<float> values;
//////////////////////////////////////////////////////////////////////////// for (int i = 0; i < filter.GetKernelData().GetDims().prod(); ++i) {
//////////////////////////////////////////////////////////////////////////// values.push_back(1.);
// RPS // std::cout << values[i] << " ";
}
std::cout << "\n";
{ filter.SetImage(&filtered);
VoxFilterAlgorithmSPR<TestVoxel> filter(Vector3i(2,3,4));
VoxImage<TestVoxel> filtered = image; filter.SetKernelNumericXZY(values);
std::vector<float> values; filter.SetABTrim(0, 2);
for(int i=0; i < filter.GetKernelData().GetDims().prod(); ++i) {
values.push_back(1.);
std::cout << values[i] << " ";
}
std::cout << "\n";
filter.SetImage(&filtered); filter.GetKernelData().PrintSelf(std::cout);
filter.SetKernelNumericXZY(values); filter.Run();
filter.SetABTrim(0,2); filtered.ExportToVtk("filter_RPS_out.vtk", 0);
}
filter.GetKernelData().PrintSelf(std::cout); {
filter.Run(); VoxImage<TestVoxel> image(Vector3i(20, 30, 40));
image[Vector3i(10, 10, 10)].Value = 1;
image[Vector3i(9, 10, 8)].Value = 2;
image.ExportToVtk("test_filter_max_original.vtk", 0);
filtered.ExportToVtk("filter_RPS_out.vtk",0); VoxFilterAlgorithmCustom<TestVoxel> filter(Vector3i(3, 3, 4));
std::vector<float> values;
for (int i = 0; i < filter.GetKernelData().GetDims().prod(); ++i) {
values.push_back(static_cast<float>(1));
} }
filter.SetImage(&image);
filter.SetKernelNumericXZY(values);
filter.SetCustomEvaluate(MaxInVector);
filter.Run();
{ image.ExportToVtk("test_filter_max.vtk", 0);
}
VoxImage<TestVoxel> image(Vector3i(20,30,40)); ////////////////////////////////////////////////////////////////////////////
image[Vector3i(10,10,10)].Value = 1; // CUDA Allocator Transfer Test //
image[Vector3i(9,10,8)].Value = 2; {
image.ExportToVtk("test_filter_max_original.vtk",0); VoxImage<TestVoxel> image(Vector3i(10, 10, 10));
image[Vector3i(5, 5, 5)].Value = 1;
VoxFilterAlgorithmLinear<TestVoxel> filter(Vector3i(3, 3, 3));
std::vector<float> values;
VoxFilterAlgorithmCustom<TestVoxel> filter(Vector3i(3,3,4)); for (int i = 0; i < filter.GetKernelData().GetDims().prod(); ++i) {
values.push_back(1.0f);
std::vector<float> values;
for(int i=0; i < filter.GetKernelData().GetDims().prod(); ++i) {
values.push_back(static_cast<float>(1));
}
filter.SetImage(&image);
filter.SetKernelNumericXZY(values);
filter.SetCustomEvaluate(MaxInVector);
filter.Run();
image.ExportToVtk("test_filter_max.vtk",0);
} }
filter.SetImage(&image);
filter.SetKernelNumericXZY(values);
// Move the kernel data and image data to VRAM to simulate CUDA transfer
filter.GetKernelData().Data().MoveToVRAM();
image.Data().MoveToVRAM();
END_TESTING; // Validate devices
if (filter.GetKernelData().Data().GetDevice() != MemoryDevice::VRAM ||
image.Data().GetDevice() != MemoryDevice::VRAM) {
#ifdef USE_CUDA
std::cerr << "Failed to move memory to VRAM." << std::endl;
#else
std::cout << "DataAllocator correctly simulates VRAM without crashing."
<< std::endl;
#endif
}
// Run the filter; The fallback CPU filter will trigger MoveToRAM
// behind the scenes inside Convolve / Evaluate.
filter.Run();
// Assert it came back to RAM if evaluated on CPU
if (image.Data().GetDevice() != MemoryDevice::RAM) {
#ifdef USE_CUDA
std::cout << "Data correctly stayed in VRAM after CUDA execution!"
<< std::endl;
#else
std::cout << "Data correctly stayed in RAM simulation." << std::endl;
#endif
}
image.ExportToVtk("test_filter_cuda_transfer.vtk", 0);
}
////////////////////////////////////////////////////////////////////////////
// CUDA ABTrim Allocator Transfer Test //
{
VoxImage<TestVoxel> image(Vector3i(10, 10, 10));
image[Vector3i(5, 5, 5)].Value = 10;
image[Vector3i(5, 5, 6)].Value = 2; // Test trimming
VoxFilterAlgorithmAbtrim<TestVoxel> filter(Vector3i(3, 3, 3));
std::vector<float> values;
for (int i = 0; i < filter.GetKernelData().GetDims().prod(); ++i) {
values.push_back(1.0f);
}
filter.SetImage(&image);
filter.SetKernelNumericXZY(values);
filter.SetABTrim(1, 1); // trim highest and lowest
// Move the kernel data and image data to VRAM to simulate CUDA transfer
filter.GetKernelData().Data().MoveToVRAM();
image.Data().MoveToVRAM();
// Run the filter
filter.Run();
// Ensure data stays on device if CUDA was toggled
if (image.Data().GetDevice() != MemoryDevice::RAM) {
#ifdef USE_CUDA
std::cout << "ABTrim correctly stayed in VRAM after CUDA execution!"
<< std::endl;
#else
std::cout << "ABTrim Data correctly stayed in RAM simulation."
<< std::endl;
#endif
}
image.ExportToVtk("test_filter_abtrim_cuda_transfer.vtk", 0);
}
END_TESTING;
} }

View File

@@ -23,85 +23,91 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include "testing-prototype.h"
#include "Math/StructuredGrid.h"
#include "Math/VoxImage.h" #include "Math/VoxImage.h"
#include "Math/StructuredGrid.h"
#include "testing-prototype.h"
using namespace uLib; using namespace uLib;
struct TestVoxel { struct TestVoxel {
Scalarf Value; Scalarf Value;
unsigned int Count; unsigned int Count;
}; };
int main() { int main() {
BEGIN_TESTING(Math StructuredGrid); BEGIN_TESTING(Math StructuredGrid);
{ // SIMPLE TESTS // { // SIMPLE TESTS //
StructuredGrid img(Vector3i(10,10,10)); StructuredGrid img(Vector3i(10, 10, 10));
img.SetSpacing(Vector3f(3,3,3)); img.SetSpacing(Vector3f(3, 3, 3));
TEST1( img.GetWorldPoint(2,0,0) == HPoint3f(6,0,0) ); TEST1(img.GetWorldPoint(2, 0, 0) == HPoint3f(6, 0, 0));
TEST1( img.GetWorldPoint(1,1,1) == HPoint3f(3,3,3) ); TEST1(img.GetWorldPoint(1, 1, 1) == HPoint3f(3, 3, 3));
img.SetPosition(Vector3f(1,1,1)); img.SetPosition(Vector3f(1, 1, 1));
TEST1( img.GetWorldPoint(1,1,1) == HPoint3f(4,4,4) ); TEST1(img.GetWorldPoint(1, 1, 1) == HPoint3f(4, 4, 4));
TEST1( img.GetLocalPoint(4,4,4) == HPoint3f(1,1,1) ); TEST1(img.GetLocalPoint(4, 4, 4) == HPoint3f(1, 1, 1));
TEST0( img.IsInsideBounds(HPoint3f(5,33,-5))); TEST0(img.IsInsideBounds(HPoint3f(5, 33, -5)));
TEST0( img.IsInsideBounds(HPoint3f(0,0,0))); TEST0(img.IsInsideBounds(HPoint3f(0, 0, 0)));
TEST1( img.IsInsideBounds(HPoint3f(1,1,1))); TEST1(img.IsInsideBounds(HPoint3f(1, 1, 1)));
}
{ // TEST WITH ORIGIN //
StructuredGrid img(Vector3i(10, 10, 10));
img.SetSpacing(Vector3f(3, 3, 3));
img.SetOrigin(Vector3f(-1, 1, -1));
img.SetPosition(Vector3f(1, 1, 1));
TEST1(img.GetWorldPoint(1, 1, 1) == HPoint3f(3, 5, 3));
}
{
VoxImage<TestVoxel> img(Vector3i(10, 10, 10));
TestVoxel zero = {0.f, 0};
img.InitVoxels(zero);
TestVoxel nonzero = {5.552368f, 0};
img[Vector3i(5, 1, 7)] = nonzero;
img[img.Find(HPoint3f(3, 3, 3))].Value = 5.552369;
img.ExportToVtk("./test_vox_image.vtk", 0);
img.ExportToVtkXml("./test_vox_image.vti", 0);
TEST1(img.GetValue(Vector3i(5, 1, 7)) == 5.552368f);
}
{
VoxImage<TestVoxel> img(Vector3i(4, 4, 4));
TestVoxel zero = {0.f, 0};
img.InitVoxels(zero);
img.SetSpacing(Vector3f(2, 2, 2));
img.SetPosition(Vector3f(-4, -4, -4));
TEST1(img.GetWorldPoint(img.GetLocalPoint(HPoint3f(5, 5, 5))) ==
HPoint3f(5, 5, 5));
}
{
VoxImage<TestVoxel> imgR(Vector3i(0, 0, 0));
imgR.ImportFromVtk("./test_vox_image.vtk");
imgR.ExportToVtk("./read_and_saved.vtk");
}
{
VoxImage<TestVoxel> img(Vector3i(4, 4, 4));
img.InitVoxels({0.f, 0});
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 4; k++) {
img[Vector3i(i, j, k)] = {static_cast<float>(i + j + k), 0};
}
}
} }
img.ExportToVti("./vti_saved.vti", 0, 1);
// img.ImportFromVtkXml("./test_vox_image.vti");
}
{ // TEST WITH ORIGIN // {
StructuredGrid img(Vector3i(10,10,10)); VoxImage<TestVoxel> img1(Vector3i(5, 5, 5));
img.SetSpacing(Vector3f(3,3,3)); VoxImage<TestVoxel> img2;
img.SetOrigin(Vector3f(-1,1,-1)); img2 = img1;
img.SetPosition(Vector3f(1,1,1)); TEST1(img1.GetDims() == img2.GetDims());
TEST1( img.GetWorldPoint(1,1,1) == HPoint3f(3,5,3) ); }
}
END_TESTING
{
VoxImage<TestVoxel> img(Vector3i(10,10,10));
TestVoxel zero = {0,0};
img.InitVoxels(zero);
TestVoxel nonzero = {5.552368, 0};
img[Vector3i(5,1,7)] = nonzero;
img[img.Find(HPoint3f(3,3,3))].Value = 5.552369;
img.ExportToVtk("./test_vox_image.vtk",0);
img.ExportToVtkXml("./test_vox_image.vti",0);
TEST1( img.GetValue(Vector3i(5,1,7)) == 5.552368f );
}
{
VoxImage<TestVoxel> img(Vector3i(4,4,4));
TestVoxel zero = {0,0};
img.InitVoxels(zero);
img.SetSpacing(Vector3f(2,2,2));
img.SetPosition(Vector3f(-4,-4,-4));
TEST1( img.GetWorldPoint(img.GetLocalPoint(HPoint3f(5,5,5))) == HPoint3f(5,5,5));
}
{
VoxImage<TestVoxel> imgR(Vector3i(0,0,0));
imgR.ImportFromVtk("./test_vox_image.vtk");
imgR.ExportToVtk("./read_and_saved.vtk");
}
{
VoxImage<TestVoxel> img1(Vector3i(5,5,5));
VoxImage<TestVoxel> img2;
img2 = img1;
TEST1( img1.GetDims() == img2.GetDims() );
}
END_TESTING
} }

View File

@@ -23,129 +23,196 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include "Math/StructuredGrid.h"
#include "Math/VoxRaytracer.h" #include "Math/VoxRaytracer.h"
#include "Math/StructuredGrid.h"
#include "testing-prototype.h" #include "testing-prototype.h"
#include <iostream>
using namespace uLib; using namespace uLib;
int Vector4f0(Vector4f c) {
int Vector4f0(Vector4f c)
{
c(3) = 0; c(3) = 0;
if ( fabs(c(0)) < 0.001 && fabs(c(1)) < 0.001 && fabs(c(2)) < 0.001 ) if (fabs(c(0)) < 0.001 && fabs(c(1)) < 0.001 && fabs(c(2)) < 0.001)
return 0; return 0;
else else
return 1; return 1;
} }
//bool Comapare(const &t1, const T2 &t2) // bool Comapare(const &t1, const T2 &t2)
//{ //{
// int out = 0; // int out = 0;
// out += t1.vox_id != t2.vox_id; // out += t1.vox_id != t2.vox_id;
// out += (fabs(t1.L) - fabs(t2.L)) > 0.001; // out += (fabs(t1.L) - fabs(t2.L)) > 0.001;
// return out == 0; // return out == 0;
//} // }
typedef VoxRaytracer Raytracer; typedef VoxRaytracer Raytracer;
int main() struct TestVoxel {
{ float Value;
BEGIN_TESTING(Math VoxRaytracer); int Count;
};
StructuredGrid img(Vector3i(2,2,2)); int main() {
img.SetSpacing(Vector3f(2,2,2)); BEGIN_TESTING(Math VoxRaytracer);
img.SetPosition(Vector3f(-2,0,-2));
StructuredGrid img(Vector3i(2, 2, 2));
img.SetSpacing(Vector3f(2, 2, 2));
img.SetPosition(Vector3f(-2, 0, -2));
{
HLine3f line;
line.origin << 0.1, 4.1, 0.1, 1;
line.direction << 0.1, -0.1, 0.1, 0;
Raytracer rt(img);
HPoint3f pt;
TEST1(rt.GetEntryPoint(line, pt));
TEST0(Vector4f0(pt - HPoint3f(0.2, 4, 0.2)));
}
{
HLine3f line;
line.origin << 4, 0, 4, 1;
line.direction << -0.1, 0.1, -0.1, 0;
Raytracer rt(img);
HPoint3f pt;
TEST1(rt.GetEntryPoint(line, pt));
TEST0(Vector4f0(pt - HPoint3f(2, 2, 2)));
}
{ // Test a point inside image //
StructuredGrid img(Vector3i(4, 4, 4));
img.SetSpacing(Vector3f(2, 2, 2));
img.SetPosition(Vector3f(-4, -4, -4));
Raytracer ray(img);
HPoint3f pt;
HLine3f line;
line.origin = HPoint3f(-3, -3, -3);
// line.direction = HVector3f(1,1,1); //
TEST1(ray.GetEntryPoint(line, pt));
TEST1(pt == HPoint3f(-3, -3, -3));
Raytracer::RayData rdata =
ray.TraceBetweenPoints(HPoint3f(-3, -3, -3), HPoint3f(3, 3, 3));
for (size_t i = 0; i < rdata.Count(); ++i) {
const Raytracer::RayData::Element &el = rdata.Data()[i];
std::cout << " " << el.vox_id << " , " << el.L << "\n";
}
}
{
HPoint3f pt1(1, -0.5, 1);
HPoint3f pt2(1, 4.5, 1);
Raytracer rt(img);
Raytracer::RayData ray = rt.TraceBetweenPoints(pt1, pt2);
TEST1(ray.Count() == 2);
TEST1(ray.Data().at(0).vox_id == 6);
TEST1(ray.Data().at(1).vox_id == 7);
ray.PrintSelf(std::cout);
}
{
HPoint3f pt1(5, 1, 1);
HPoint3f pt2(-3, 1, 1);
Raytracer rt(img);
Raytracer::RayData ray = rt.TraceBetweenPoints(pt1, pt2);
TEST1(ray.Count() == 2);
TEST1(ray.Data().at(0).vox_id == 6);
TEST1(ray.Data().at(1).vox_id == 4);
ray.PrintSelf(std::cout);
}
{
HPoint3f pt1(1, 1, 1);
HPoint3f pt2(-1, 3, -1);
Raytracer rt(img);
Raytracer::RayData ray = rt.TraceBetweenPoints(pt1, pt2);
TEST1(ray.Count() == 4);
TEST1(ray.Data().at(0).vox_id == 6);
TEST1(ray.Data().at(1).vox_id == 4);
TEST1(ray.Data().at(2).vox_id == 5);
TEST1(ray.Data().at(3).vox_id == 1);
ray.PrintSelf(std::cout);
}
#ifdef USE_CUDA
{
std::cout << "\n--- Testing CUDA Raytracer Accumulator ---\n";
Raytracer rt(img);
{ {
HLine3f line; HPoint3f pt1(1, -0.5, 1);
line.origin << 0.1, 4.1, 0.1, 1; HPoint3f pt2(1, 4.5, 1);
line.direction << 0.1, -0.1, 0.1,0; HPoint3f pts1[1] = {pt1};
Raytracer rt(img); HPoint3f pts2[1] = {pt2};
HPoint3f pt; Raytracer::RayData ray_cuda[1];
TEST1( rt.GetEntryPoint(line,pt) ); rt.TraceBetweenPointsCUDA(pts1, pts2, 1, ray_cuda);
TEST0( Vector4f0( pt - HPoint3f(0.2,4,0.2) ) ); TEST1(ray_cuda[0].Count() == 2);
TEST1(ray_cuda[0].Data().at(0).vox_id == 6);
TEST1(ray_cuda[0].Data().at(1).vox_id == 7);
} }
{ {
HLine3f line; HPoint3f pt1(5, 1, 1);
line.origin << 4,0,4, 1; HPoint3f pt2(-3, 1, 1);
line.direction << -0.1, 0.1, -0.1, 0; HPoint3f pts1[1] = {pt1};
Raytracer rt(img); HPoint3f pts2[1] = {pt2};
HPoint3f pt; Raytracer::RayData ray_cuda[1];
TEST1( rt.GetEntryPoint(line,pt) ); rt.TraceBetweenPointsCUDA(pts1, pts2, 1, ray_cuda);
TEST0( Vector4f0( pt - HPoint3f(2,2,2) ) ); TEST1(ray_cuda[0].Count() == 2);
} TEST1(ray_cuda[0].Data().at(0).vox_id == 6);
TEST1(ray_cuda[0].Data().at(1).vox_id == 4);
{ // Test a point inside image //
StructuredGrid img(Vector3i(4,4,4));
img.SetSpacing(Vector3f(2,2,2));
img.SetPosition(Vector3f(-4,-4,-4));
Raytracer ray(img);
HPoint3f pt;
HLine3f line;
line.origin = HPoint3f(-3,-3,-3);
// line.direction = HVector3f(1,1,1); //
TEST1( ray.GetEntryPoint(line,pt) );
TEST1( pt == HPoint3f(-3,-3,-3) );
Raytracer::RayData rdata = ray.TraceBetweenPoints(HPoint3f(-3,-3,-3), HPoint3f(3,3,3));
for(const Raytracer::RayData::Element &el : rdata.Data())
{
std::cout << " " << el.vox_id << " , " << el.L << "\n";
}
}
{
HPoint3f pt1(1,-0.5,1);
HPoint3f pt2(1,4.5,1);
Raytracer rt(img);
Raytracer::RayData ray = rt.TraceBetweenPoints(pt1,pt2);
TEST1( ray.Data().size() == 2 );
TEST1( ray.Data().at(0).vox_id == 6 );
TEST1( ray.Data().at(1).vox_id == 7 );
ray.PrintSelf(std::cout);
} }
{ {
HPoint3f pt1(5,1,1); HPoint3f pt1(1, 1, 1);
HPoint3f pt2(-3,1,1); HPoint3f pt2(-1, 3, -1);
Raytracer rt(img); HPoint3f pts1[1] = {pt1};
HPoint3f pts2[1] = {pt2};
Raytracer::RayData ray = rt.TraceBetweenPoints(pt1,pt2); Raytracer::RayData ray_cuda[1];
TEST1( ray.Data().size() == 2 ); rt.TraceBetweenPointsCUDA(pts1, pts2, 1, ray_cuda);
TEST1( ray.Data().at(0).vox_id == 6 ); TEST1(ray_cuda[0].Count() == 4);
TEST1( ray.Data().at(1).vox_id == 4 ); TEST1(ray_cuda[0].Data().at(0).vox_id == 6);
ray.PrintSelf(std::cout); TEST1(ray_cuda[0].Data().at(1).vox_id == 4);
TEST1(ray_cuda[0].Data().at(2).vox_id == 5);
TEST1(ray_cuda[0].Data().at(3).vox_id == 1);
} }
{ VoxImage<TestVoxel> img_cuda(Vector3i(4, 4, 4));
HPoint3f pt1(1,1,1); img_cuda.SetSpacing(Vector3f(2, 2, 2));
HPoint3f pt2(-1,3,-1); img_cuda.SetPosition(Vector3f(-4, -4, -4));
Raytracer rt(img);
Raytracer::RayData ray = rt.TraceBetweenPoints(pt1,pt2); Raytracer ray(img_cuda);
TEST1( ray.Data().size() == 4 );
TEST1( ray.Data().at(0).vox_id == 6 );
TEST1( ray.Data().at(1).vox_id == 4 );
TEST1( ray.Data().at(2).vox_id == 5 );
TEST1( ray.Data().at(3).vox_id == 1 );
ray.PrintSelf(std::cout);
}
END_TESTING HLine3f line1;
line1.origin << -3, -3, -3, 1;
line1.direction << 1, 1, 1, 0;
HLine3f line2;
line2.origin << -3, -3, 1, 1;
line2.direction << 1, 1, -1, 0;
HLine3f lines[2] = {line1, line2};
// Execute CUDA kernel wrapper over target VoxImage mapped internally into
// VRAM
ray.AccumulateLinesCUDA(lines, 2, img_cuda);
// Validate device synchronization returned data correctly pulling back to
// host
TEST1(img_cuda.Data().GetDevice() !=
MemoryDevice::RAM); // Confirms VRAM executed
// Pull down checking values
float l_val = img_cuda[img_cuda.Find(Vector4f(-3, -3, -3, 1))].Value;
std::cout << "Accumulated Voxel test trace point length returned: " << l_val
<< "\n";
TEST1(l_val > 0.1f);
}
#endif
END_TESTING
} }

View File

@@ -0,0 +1,211 @@
/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
------------------------------------------------------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
//////////////////////////////////////////////////////////////////////////////*/
#include "Math/StructuredGrid.h"
#include "Math/VoxRaytracer.h"
#include "testing-prototype.h"
#include <chrono>
#include <iostream>
#include <random>
using namespace uLib;
typedef VoxRaytracer Raytracer;
int main() {
BEGIN_TESTING(Math VoxRaytracer Extended Benchmark);
std::cout << "\n=============================================\n";
std::cout << " VoxRaytracer CPU vs CUDA Benchmark Test\n";
std::cout << "=============================================\n\n";
// Create a 100x100x100 grid (1 million voxels)
StructuredGrid img(Vector3i(100, 100, 100));
img.SetSpacing(Vector3f(1.0f, 1.0f, 1.0f));
img.SetPosition(Vector3f(-50.0f, -50.0f, -50.0f));
Raytracer rt(img);
const size_t NUM_RAYS = 1000000;
std::cout << "Generating " << NUM_RAYS
<< " random ray pairs across a 100x100x100 grid...\n";
std::vector<HPoint3f> in_pts(NUM_RAYS);
std::vector<HPoint3f> out_pts(NUM_RAYS);
// Use a fixed seed for reproducible tests
std::random_device rd;
std::mt19937 gen(rd());
// The grid spans from -50 to 50 on each axis
std::uniform_real_distribution<float> dist(-49.9f, 49.9f);
// Pick a random face for in/out to ensure rays cross the volume
std::uniform_int_distribution<int> face_dist(0, 5);
for (size_t i = 0; i < NUM_RAYS; ++i) {
HPoint3f p1, p2;
// Generate point 1 on a random face
int f1 = face_dist(gen);
p1(0) = (f1 == 0) ? -50.0f : (f1 == 1) ? 50.0f : dist(gen);
p1(1) = (f1 == 2) ? -50.0f : (f1 == 3) ? 50.0f : dist(gen);
p1(2) = (f1 == 4) ? -50.0f : (f1 == 5) ? 50.0f : dist(gen);
p1(3) = 1.0f;
// Generate point 2 on a different face
int f2;
do {
f2 = face_dist(gen);
} while (
f1 == f2 ||
f1 / 2 ==
f2 / 2); // Avoid same face or opposite face trivially if desired
p2(0) = (f2 == 0) ? -50.0f : (f2 == 1) ? 50.0f : dist(gen);
p2(1) = (f2 == 2) ? -50.0f : (f2 == 3) ? 50.0f : dist(gen);
p2(2) = (f2 == 4) ? -50.0f : (f2 == 5) ? 50.0f : dist(gen);
p2(3) = 1.0f;
in_pts[i] = p1;
out_pts[i] = p2;
}
std::vector<Raytracer::RayData> cpu_results(NUM_RAYS);
std::cout << "\nRunning CPU Raytracing...\n";
auto start_cpu = std::chrono::high_resolution_clock::now();
for (size_t i = 0; i < NUM_RAYS; ++i) {
cpu_results[i] = rt.TraceBetweenPoints(in_pts[i], out_pts[i]);
}
auto end_cpu = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> cpu_ms = end_cpu - start_cpu;
std::cout << "CPU Execution Time: " << cpu_ms.count() << " ms\n";
#ifdef USE_CUDA
std::vector<Raytracer::RayData> cuda_results(NUM_RAYS);
int max_elements_per_ray =
400; // 100x100x100 grid max trace length usually ~300 items
std::cout << "\nPre-Allocating Data to VRAM...\n";
// Pre-allocate input and output points to VRAM
HPoint3f *d_in_pts;
HPoint3f *d_out_pts;
size_t pts_size = NUM_RAYS * sizeof(HPoint3f);
cudaMalloc(&d_in_pts, pts_size);
cudaMalloc(&d_out_pts, pts_size);
cudaMemcpy(d_in_pts, in_pts.data(), pts_size, cudaMemcpyHostToDevice);
cudaMemcpy(d_out_pts, out_pts.data(), pts_size, cudaMemcpyHostToDevice);
// Pre-allocate elements output arrays in VRAM via DataAllocator
for (size_t i = 0; i < NUM_RAYS; ++i) {
cuda_results[i].Data().resize(max_elements_per_ray);
cuda_results[i].Data().MoveToVRAM();
}
std::cout << "Running CUDA Raytracing...\n";
auto start_cuda = std::chrono::high_resolution_clock::now();
float kernel_time_ms = 0.0f;
rt.TraceBetweenPointsCUDA(d_in_pts, d_out_pts, NUM_RAYS, cuda_results.data(),
max_elements_per_ray, &kernel_time_ms);
auto end_cuda = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> cuda_ms = end_cuda - start_cuda;
// Free explicit input pointers
cudaFree(d_in_pts);
cudaFree(d_out_pts);
// Also query memory usage info
size_t free_byte;
size_t total_byte;
cudaMemGetInfo(&free_byte, &total_byte);
double free_db = (double)free_byte / (1024.0 * 1024.0);
double total_db = (double)total_byte / (1024.0 * 1024.0);
double used_db = total_db - free_db;
std::cout << "CUDA Kernel Exec Time: " << kernel_time_ms << " ms\n";
std::cout << "CUDA Total Time (API): " << cuda_ms.count() << " ms\n";
std::cout << "CUDA Total Time Spdup: " << (cpu_ms.count() / cuda_ms.count())
<< "x\n";
if (kernel_time_ms > 0.0f) {
std::cout << "CUDA Kernel Speedup : " << (cpu_ms.count() / kernel_time_ms)
<< "x\n";
}
std::cout << "CUDA VRAM Usage Est. : " << used_db << " MB out of " << total_db
<< " MB total\n";
std::cout << "\nVerifying CUDA results against CPU...\n";
size_t mismatches = 0;
for (size_t i = 0; i < NUM_RAYS; ++i) {
const auto &cpu_ray = cpu_results[i];
const auto &cuda_ray = cuda_results[i];
if (cpu_ray.Count() != cuda_ray.Count() ||
std::abs(cpu_ray.TotalLength() - cuda_ray.TotalLength()) > 1e-3) {
if (mismatches < 5) {
std::cout << "Mismatch at ray " << i
<< ": CPU count=" << cpu_ray.Count()
<< ", len=" << cpu_ray.TotalLength()
<< " vs CUDA count=" << cuda_ray.Count()
<< ", len=" << cuda_ray.TotalLength() << "\n";
}
mismatches++;
continue;
}
// Check elements
for (size_t j = 0; j < cpu_ray.Count(); ++j) {
if (cpu_ray.Data()[j].vox_id != cuda_ray.Data()[j].vox_id ||
std::abs(cpu_ray.Data()[j].L - cuda_ray.Data()[j].L) > 1e-3) {
if (mismatches < 5) {
std::cout << "Mismatch at ray " << i << ", element " << j
<< ": CPU id=" << cpu_ray.Data()[j].vox_id
<< ", L=" << cpu_ray.Data()[j].L
<< " vs CUDA id=" << cuda_ray.Data()[j].vox_id
<< ", L=" << cuda_ray.Data()[j].L << "\n";
}
mismatches++;
break;
}
}
}
if (mismatches == 0) {
std::cout << "SUCCESS! All " << NUM_RAYS
<< " rays perfectly match between CPU and CUDA.\n";
} else {
std::cout << "FAILED! " << mismatches << " rays contain mismatched data.\n";
}
TEST1(mismatches == 0);
#else
std::cout << "\nUSE_CUDA is not defined. Skipping CUDA benchmarking.\n";
#endif
std::cout << "=============================================\n";
END_TESTING
}

58
src/Python/CMakeLists.txt Normal file
View File

@@ -0,0 +1,58 @@
set(HEADERS "")
set(SOURCES
module.cpp
core_bindings.cpp
math_bindings.cpp
math_filters_bindings.cpp
)
# Use pybind11 to add the python module
pybind11_add_module(uLib_python module.cpp core_bindings.cpp math_bindings.cpp math_filters_bindings.cpp)
# Link against our C++ libraries
target_link_libraries(uLib_python PRIVATE
${PACKAGE_LIBPREFIX}Core
${PACKAGE_LIBPREFIX}Math
)
# Include directories from Core and Math are automatically handled if target_include_directories were set appropriately,
# but we might need to manually include them if they aren't INTERFACE includes.
target_include_directories(uLib_python PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_BINARY_DIR}
)
# Install uLib_python within the uLib install target
install(TARGETS uLib_python
EXPORT "${PROJECT_NAME}Targets"
RUNTIME DESTINATION ${INSTALL_BIN_DIR} COMPONENT bin
LIBRARY DESTINATION ${INSTALL_LIB_DIR} COMPONENT lib
ARCHIVE DESTINATION ${INSTALL_LIB_DIR} COMPONENT lib
)
# --- Python Tests ---------------------------------------------------------- #
if(BUILD_TESTING)
find_package(Python3 COMPONENTS Interpreter REQUIRED)
add_test(NAME pybind_general
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/pybind_test.py)
set_tests_properties(pybind_general PROPERTIES
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:uLib_python>:${PROJECT_SOURCE_DIR}/src/Python")
add_test(NAME pybind_core
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/core_pybind_test.py)
set_tests_properties(pybind_core PROPERTIES
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:uLib_python>:${PROJECT_SOURCE_DIR}/src/Python")
add_test(NAME pybind_math
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/math_pybind_test.py)
set_tests_properties(pybind_math PROPERTIES
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:uLib_python>:${PROJECT_SOURCE_DIR}/src/Python")
add_test(NAME pybind_math_filters
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/math_filters_test.py)
set_tests_properties(pybind_math_filters PROPERTIES
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:uLib_python>:${PROJECT_SOURCE_DIR}/src/Python")
endif()

View File

@@ -0,0 +1,30 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "Core/Object.h"
#include "Core/Timer.h"
#include "Core/Options.h"
#include "Core/Uuid.h"
namespace py = pybind11;
using namespace uLib;
void init_core(py::module_ &m) {
py::class_<Object, std::shared_ptr<Object>>(m, "Object")
.def(py::init<>())
.def("DeepCopy", &Object::DeepCopy);
py::class_<Timer>(m, "Timer")
.def(py::init<>())
.def("Start", &Timer::Start)
.def("StopWatch", &Timer::StopWatch);
py::class_<Options>(m, "Options")
.def(py::init<const char*>(), py::arg("str") = "Program options")
.def("parse_config_file", py::overload_cast<const char*>(&Options::parse_config_file))
.def("save_config_file", &Options::save_config_file)
.def("count", &Options::count);
py::class_<TypeRegister>(m, "TypeRegister")
.def_static("Controller", &TypeRegister::Controller, py::return_value_policy::reference_internal);
}

View File

@@ -0,0 +1,385 @@
#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include <pybind11/numpy.h>
#include "Math/Dense.h"
#include "Math/Transform.h"
#include "Math/Geometry.h"
#include "Math/ContainerBox.h"
#include "Math/StructuredData.h"
#include "Math/StructuredGrid.h"
#include "Math/Structured2DGrid.h"
#include "Math/Structured4DGrid.h"
#include "Math/TriangleMesh.h"
#include "Math/VoxRaytracer.h"
#include "Math/Accumulator.h"
#include "Math/VoxImage.h"
namespace py = pybind11;
using namespace uLib;
PYBIND11_MAKE_OPAQUE(uLib::Vector<Scalari>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Scalarui>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Scalarl>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Scalarul>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Scalarf>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Scalard>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector3f>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector3i>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector4f>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector4i>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector3d>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector4d>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Voxel>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<VoxRaytracer::RayData::Element>);
template <typename MatrixType>
void bind_eigen_type(py::module_ &m, const char *name) {
using Scalar = typename MatrixType::Scalar;
constexpr bool is_vector = MatrixType::IsVectorAtCompileTime;
// Default constructor (zeros)
m.def(name, []() -> MatrixType {
if constexpr (MatrixType::RowsAtCompileTime == Eigen::Dynamic || MatrixType::ColsAtCompileTime == Eigen::Dynamic) {
return MatrixType(); // Empty dynamic matrix
} else {
return MatrixType::Zero(); // Zero static matrix
}
});
// Specialized constructor for dynamic matrices
if constexpr (MatrixType::RowsAtCompileTime == Eigen::Dynamic || MatrixType::ColsAtCompileTime == Eigen::Dynamic) {
m.def(name, [](int rows, int cols) -> MatrixType {
MatrixType mat;
mat.setZero(rows, cols);
return mat;
});
}
// Initialize from list
m.def(name, [](py::list l) -> MatrixType {
MatrixType mat;
if constexpr (is_vector) {
mat.setZero(l.size());
for (size_t i = 0; i < l.size(); ++i) {
mat(i) = l[i].cast<Scalar>();
}
} else {
int rows = MatrixType::RowsAtCompileTime == Eigen::Dynamic ? (int)std::sqrt(l.size()) : MatrixType::RowsAtCompileTime;
int cols = MatrixType::ColsAtCompileTime == Eigen::Dynamic ? (int)std::sqrt(l.size()) : MatrixType::ColsAtCompileTime;
mat.setZero(rows, cols);
for (size_t i = 0; i < (size_t)l.size(); ++i) {
mat(i / cols, i % cols) = l[i].cast<Scalar>();
}
}
return mat;
});
// Initialize from py::array
m.def(name, [](py::array_t<Scalar, py::array::c_style | py::array::forcecast> arr) -> MatrixType {
auto buf = arr.request();
MatrixType mat;
if constexpr (is_vector) {
mat.setZero(buf.size);
Scalar* ptr = static_cast<Scalar*>(buf.ptr);
for (ssize_t i = 0; i < buf.size; ++i) mat(i) = ptr[i];
} else {
int rows = buf.shape.size() > 0 ? (int)buf.shape[0] : 1;
int cols = buf.shape.size() > 1 ? (int)buf.shape[1] : 1;
mat.setZero(rows, cols);
Scalar* ptr = static_cast<Scalar*>(buf.ptr);
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
mat(i, j) = ptr[i * cols + j];
}
}
}
return mat;
});
}
void init_math(py::module_ &m) {
// 1. Basic Eigen Types (Vectors and Matrices)
bind_eigen_type<Vector1f>(m, "Vector1f");
bind_eigen_type<Vector2f>(m, "Vector2f");
bind_eigen_type<Vector3f>(m, "Vector3f");
bind_eigen_type<Vector4f>(m, "Vector4f");
bind_eigen_type<Vector1i>(m, "Vector1i");
bind_eigen_type<Vector2i>(m, "Vector2i");
bind_eigen_type<Vector3i>(m, "Vector3i");
bind_eigen_type<Vector4i>(m, "Vector4i");
bind_eigen_type<Vector1d>(m, "Vector1d");
bind_eigen_type<Vector2d>(m, "Vector2d");
bind_eigen_type<Vector3d>(m, "Vector3d");
bind_eigen_type<Vector4d>(m, "Vector4d");
bind_eigen_type<Matrix2f>(m, "Matrix2f");
bind_eigen_type<Matrix3f>(m, "Matrix3f");
bind_eigen_type<Matrix4f>(m, "Matrix4f");
bind_eigen_type<Matrix2i>(m, "Matrix2i");
bind_eigen_type<Matrix3i>(m, "Matrix3i");
bind_eigen_type<Matrix4i>(m, "Matrix4i");
bind_eigen_type<Matrix2d>(m, "Matrix2d");
bind_eigen_type<Matrix3d>(m, "Matrix3d");
bind_eigen_type<Matrix4d>(m, "Matrix4d");
bind_eigen_type<MatrixXi>(m, "MatrixXi");
bind_eigen_type<MatrixXf>(m, "MatrixXf");
bind_eigen_type<MatrixXd>(m, "MatrixXd");
// 2. Homogeneous types
py::class_<HPoint3f>(m, "HPoint3f")
.def(py::init<>())
.def(py::init<float, float, float>())
.def(py::init<Vector3f &>());
py::class_<HVector3f>(m, "HVector3f")
.def(py::init<>())
.def(py::init<float, float, float>())
.def(py::init<Vector3f &>());
py::class_<HLine3f>(m, "HLine3f")
.def(py::init<>())
.def_readwrite("origin", &HLine3f::origin)
.def_readwrite("direction", &HLine3f::direction);
py::class_<HError3f>(m, "HError3f")
.def(py::init<>())
.def_readwrite("position_error", &HError3f::position_error)
.def_readwrite("direction_error", &HError3f::direction_error);
// 3. Dynamic Vectors (uLib::Vector)
py::bind_vector<uLib::Vector<Scalari>>(m, "Vector_i")
.def("MoveToVRAM", &uLib::Vector<Scalari>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Scalari>::MoveToRAM);
py::bind_vector<uLib::Vector<Scalarui>>(m, "Vector_ui")
.def("MoveToVRAM", &uLib::Vector<Scalarui>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Scalarui>::MoveToRAM);
py::bind_vector<uLib::Vector<Scalarl>>(m, "Vector_l")
.def("MoveToVRAM", &uLib::Vector<Scalarl>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Scalarl>::MoveToRAM);
py::bind_vector<uLib::Vector<Scalarul>>(m, "Vector_ul")
.def("MoveToVRAM", &uLib::Vector<Scalarul>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Scalarul>::MoveToRAM);
py::bind_vector<uLib::Vector<Scalarf>>(m, "Vector_f")
.def("MoveToVRAM", &uLib::Vector<Scalarf>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Scalarf>::MoveToRAM);
py::bind_vector<uLib::Vector<Scalard>>(m, "Vector_d")
.def("MoveToVRAM", &uLib::Vector<Scalard>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Scalard>::MoveToRAM);
py::bind_vector<uLib::Vector<Vector3f>>(m, "Vector_Vector3f")
.def("MoveToVRAM", &uLib::Vector<Vector3f>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Vector3f>::MoveToRAM);
py::bind_vector<uLib::Vector<Vector3i>>(m, "Vector_Vector3i")
.def("MoveToVRAM", &uLib::Vector<Vector3i>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Vector3i>::MoveToRAM);
py::bind_vector<uLib::Vector<Vector4f>>(m, "Vector_Vector4f")
.def("MoveToVRAM", &uLib::Vector<Vector4f>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Vector4f>::MoveToRAM);
py::bind_vector<uLib::Vector<Vector4i>>(m, "Vector_Vector4i")
.def("MoveToVRAM", &uLib::Vector<Vector4i>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Vector4i>::MoveToRAM);
py::bind_vector<uLib::Vector<Vector3d>>(m, "Vector_Vector3d")
.def("MoveToVRAM", &uLib::Vector<Vector3d>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Vector3d>::MoveToRAM);
py::bind_vector<uLib::Vector<Vector4d>>(m, "Vector_Vector4d")
.def("MoveToVRAM", &uLib::Vector<Vector4d>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Vector4d>::MoveToRAM);
py::bind_vector<uLib::Vector<Voxel>>(m, "Vector_Voxel")
.def("MoveToVRAM", &uLib::Vector<Voxel>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<Voxel>::MoveToRAM);
py::bind_vector<uLib::Vector<VoxRaytracer::RayData::Element>>(m, "Vector_VoxRaytracerRayDataElement")
.def("MoveToVRAM", &uLib::Vector<VoxRaytracer::RayData::Element>::MoveToVRAM)
.def("MoveToRAM", &uLib::Vector<VoxRaytracer::RayData::Element>::MoveToRAM);
// 4. Accumulators
py::class_<Accumulator_Mean<float>>(m, "Accumulator_Mean_f")
.def(py::init<>())
.def("AddPass", &Accumulator_Mean<float>::AddPass)
.def("__call__", py::overload_cast<const float>(&Accumulator_Mean<float>::operator()))
.def("__call__", py::overload_cast<>(&Accumulator_Mean<float>::operator(), py::const_));
py::class_<Accumulator_Mean<double>>(m, "Accumulator_Mean_d")
.def(py::init<>())
.def("AddPass", &Accumulator_Mean<double>::AddPass)
.def("__call__", py::overload_cast<const double>(&Accumulator_Mean<double>::operator()))
.def("__call__", py::overload_cast<>(&Accumulator_Mean<double>::operator(), py::const_));
py::class_<Accumulator_ABTrim<float>>(m, "Accumulator_ABTrim_f")
.def(py::init<>())
.def("SetABTrim", &Accumulator_ABTrim<float>::SetABTrim)
.def("__iadd__", [](Accumulator_ABTrim<float> &self, float val) { self += val; return &self; })
.def("__call__", &Accumulator_ABTrim<float>::operator());
py::class_<Accumulator_ABTrim<double>>(m, "Accumulator_ABTrim_d")
.def(py::init<>())
.def("SetABTrim", &Accumulator_ABTrim<double>::SetABTrim)
.def("__iadd__", [](Accumulator_ABTrim<double> &self, double val) { self += val; return &self; })
.def("__call__", &Accumulator_ABTrim<double>::operator());
py::class_<Accumulator_ABClip<float>>(m, "Accumulator_ABClip_f")
.def(py::init<>())
.def("SetABTrim", &Accumulator_ABClip<float>::SetABTrim)
.def("__iadd__", [](Accumulator_ABClip<float> &self, float val) { self += val; return &self; })
.def("__call__", &Accumulator_ABClip<float>::operator());
py::class_<Accumulator_ABClip<double>>(m, "Accumulator_ABClip_d")
.def(py::init<>())
.def("SetABTrim", &Accumulator_ABClip<double>::SetABTrim)
.def("__iadd__", [](Accumulator_ABClip<double> &self, double val) { self += val; return &self; })
.def("__call__", &Accumulator_ABClip<double>::operator());
// 5. Core Math Structures
py::class_<AffineTransform>(m, "AffineTransform")
.def(py::init<>())
.def("GetWorldMatrix", &AffineTransform::GetWorldMatrix)
.def("SetPosition", &AffineTransform::SetPosition)
.def("GetPosition", &AffineTransform::GetPosition)
.def("Translate", &AffineTransform::Translate)
.def("Scale", &AffineTransform::Scale)
.def("SetRotation", &AffineTransform::SetRotation)
.def("GetRotation", &AffineTransform::GetRotation)
.def("Rotate", py::overload_cast<const Matrix3f &>(&AffineTransform::Rotate))
.def("Rotate", py::overload_cast<const Vector3f>(&AffineTransform::Rotate))
.def("EulerYZYRotate", &AffineTransform::EulerYZYRotate)
.def("FlipAxes", &AffineTransform::FlipAxes);
py::class_<Geometry, AffineTransform>(m, "Geometry")
.def(py::init<>())
.def("GetWorldPoint", py::overload_cast<const Vector4f &>(&Geometry::GetWorldPoint, py::const_))
.def("GetLocalPoint", py::overload_cast<const Vector4f &>(&Geometry::GetLocalPoint, py::const_));
py::class_<ContainerBox, AffineTransform>(m, "ContainerBox")
.def(py::init<>())
.def("SetOrigin", &ContainerBox::SetOrigin)
.def("GetOrigin", &ContainerBox::GetOrigin)
.def("SetSize", &ContainerBox::SetSize)
.def("GetSize", &ContainerBox::GetSize)
.def("GetWorldMatrix", &ContainerBox::GetWorldMatrix)
.def("GetWorldPoint", py::overload_cast<const Vector4f &>(&ContainerBox::GetWorldPoint, py::const_))
.def("GetLocalPoint", py::overload_cast<const Vector4f &>(&ContainerBox::GetLocalPoint, py::const_));
py::enum_<StructuredData::_Order>(m, "StructuredDataOrder")
.value("CustomOrder", StructuredData::CustomOrder)
.value("XYZ", StructuredData::XYZ)
.value("XZY", StructuredData::XZY)
.value("YXZ", StructuredData::YXZ)
.value("YZX", StructuredData::YZX)
.value("ZXY", StructuredData::ZXY)
.value("ZYX", StructuredData::ZYX)
.export_values();
py::class_<StructuredData>(m, "StructuredData")
.def(py::init<const Vector3i &>())
.def("GetDims", &StructuredData::GetDims)
.def("SetDims", &StructuredData::SetDims)
.def("GetIncrements", &StructuredData::GetIncrements)
.def("SetIncrements", &StructuredData::SetIncrements)
.def("SetDataOrder", &StructuredData::SetDataOrder)
.def("GetDataOrder", &StructuredData::GetDataOrder)
.def("IsInsideGrid", &StructuredData::IsInsideGrid)
.def("Map", &StructuredData::Map)
.def("UnMap", &StructuredData::UnMap);
py::class_<StructuredGrid, ContainerBox, StructuredData>(m, "StructuredGrid")
.def(py::init<const Vector3i &>())
.def("SetSpacing", &StructuredGrid::SetSpacing)
.def("GetSpacing", &StructuredGrid::GetSpacing)
.def("IsInsideBounds", &StructuredGrid::IsInsideBounds)
.def("Find", [](StructuredGrid &self, Vector3f pt) {
return self.Find(HPoint3f(pt));
});
py::class_<Structured2DGrid>(m, "Structured2DGrid")
.def(py::init<>())
.def("SetDims", &Structured2DGrid::SetDims)
.def("GetDims", &Structured2DGrid::GetDims)
.def("IsInsideGrid", &Structured2DGrid::IsInsideGrid)
.def("Map", &Structured2DGrid::Map)
.def("UnMap", &Structured2DGrid::UnMap)
.def("SetPhysicalSpace", &Structured2DGrid::SetPhysicalSpace)
.def("GetSpacing", &Structured2DGrid::GetSpacing)
.def("GetOrigin", &Structured2DGrid::GetOrigin)
.def("IsInsideBounds", &Structured2DGrid::IsInsideBounds)
.def("PhysicsToUnitSpace", &Structured2DGrid::PhysicsToUnitSpace)
.def("UnitToPhysicsSpace", &Structured2DGrid::UnitToPhysicsSpace)
.def("SetDebug", &Structured2DGrid::SetDebug);
py::class_<Structured4DGrid>(m, "Structured4DGrid")
.def(py::init<>())
.def("SetDims", &Structured4DGrid::SetDims)
.def("GetDims", &Structured4DGrid::GetDims)
.def("IsInsideGrid", &Structured4DGrid::IsInsideGrid)
.def("Map", &Structured4DGrid::Map)
.def("UnMap", &Structured4DGrid::UnMap)
.def("SetPhysicalSpace", &Structured4DGrid::SetPhysicalSpace)
.def("GetSpacing", &Structured4DGrid::GetSpacing)
.def("GetOrigin", &Structured4DGrid::GetOrigin)
.def("IsInsideBounds", &Structured4DGrid::IsInsideBounds)
.def("PhysicsToUnitSpace", &Structured4DGrid::PhysicsToUnitSpace)
.def("UnitToPhysicsSpace", &Structured4DGrid::UnitToPhysicsSpace)
.def("SetDebug", &Structured4DGrid::SetDebug);
// 6. High-level Structures
py::class_<Voxel>(m, "Voxel")
.def(py::init<>())
.def_readwrite("Value", &Voxel::Value)
.def_readwrite("Count", &Voxel::Count);
py::class_<Abstract::VoxImage, StructuredGrid>(m, "AbstractVoxImage")
.def("GetValue", py::overload_cast<const Vector3i &>(&Abstract::VoxImage::GetValue, py::const_))
.def("GetValue", py::overload_cast<const int>(&Abstract::VoxImage::GetValue, py::const_))
.def("SetValue", py::overload_cast<const Vector3i &, float>(&Abstract::VoxImage::SetValue))
.def("SetValue", py::overload_cast<const int, float>(&Abstract::VoxImage::SetValue))
.def("ExportToVtk", &Abstract::VoxImage::ExportToVtk)
.def("ExportToVti", &Abstract::VoxImage::ExportToVti)
.def("ImportFromVtk", &Abstract::VoxImage::ImportFromVtk)
.def("ImportFromVti", &Abstract::VoxImage::ImportFromVti);
py::class_<VoxImage<Voxel>, Abstract::VoxImage>(m, "VoxImage")
.def(py::init<>())
.def(py::init<const Vector3i &>())
.def("Data", &VoxImage<Voxel>::Data, py::return_value_policy::reference_internal)
.def("InitVoxels", &VoxImage<Voxel>::InitVoxels)
.def("Abs", &VoxImage<Voxel>::Abs)
.def("clipImage", py::overload_cast<const Vector3i, const Vector3i>(&VoxImage<Voxel>::clipImage, py::const_))
.def("clipImage", py::overload_cast<const HPoint3f, const HPoint3f>(&VoxImage<Voxel>::clipImage, py::const_))
.def("clipImage", py::overload_cast<const float>(&VoxImage<Voxel>::clipImage, py::const_))
.def("maskImage", py::overload_cast<const HPoint3f, const HPoint3f, float>(&VoxImage<Voxel>::maskImage, py::const_))
.def("maskImage", py::overload_cast<const float, float, float>(&VoxImage<Voxel>::maskImage, py::const_), py::arg("threshold"), py::arg("belowValue") = 0, py::arg("aboveValue") = 0)
.def("fixVoxels", py::overload_cast<const float, float>(&VoxImage<Voxel>::fixVoxels, py::const_))
.def("__getitem__", py::overload_cast<unsigned int>(&VoxImage<Voxel>::operator[]))
.def("__getitem__", py::overload_cast<const Vector3i &>(&VoxImage<Voxel>::operator[]));
py::class_<TriangleMesh>(m, "TriangleMesh")
.def(py::init<>())
.def("AddPoint", &TriangleMesh::AddPoint)
.def("AddTriangle", py::overload_cast<const Vector3i &>(&TriangleMesh::AddTriangle))
.def("Points", &TriangleMesh::Points, py::return_value_policy::reference_internal)
.def("Triangles", &TriangleMesh::Triangles, py::return_value_policy::reference_internal);
py::class_<VoxRaytracer::RayData::Element>(m, "VoxRaytracerRayDataElement")
.def(py::init<>())
.def_readwrite("vox_id", &VoxRaytracer::RayData::Element::vox_id)
.def_readwrite("L", &VoxRaytracer::RayData::Element::L);
py::class_<VoxRaytracer::RayData>(m, "VoxRaytracerRayData")
.def(py::init<>())
.def("AppendRay", &VoxRaytracer::RayData::AppendRay)
.def("Data", py::overload_cast<>(&VoxRaytracer::RayData::Data), py::return_value_policy::reference_internal)
.def("Count", &VoxRaytracer::RayData::Count)
.def("TotalLength", &VoxRaytracer::RayData::TotalLength)
.def("SetCount", &VoxRaytracer::RayData::SetCount)
.def("SetTotalLength", &VoxRaytracer::RayData::SetTotalLength);
py::class_<VoxRaytracer>(m, "VoxRaytracer")
.def(py::init<StructuredGrid &>(), py::keep_alive<1, 2>())
.def("GetImage", &VoxRaytracer::GetImage, py::return_value_policy::reference_internal)
.def("TraceLine", &VoxRaytracer::TraceLine)
.def("TraceBetweenPoints", &VoxRaytracer::TraceBetweenPoints);
}

View File

@@ -0,0 +1,100 @@
#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
#include <pybind11/stl.h>
#include "Math/VoxImage.h"
#include "Math/VoxImageFilter.h"
#include "Math/VoxImageFilterLinear.hpp"
#include "Math/VoxImageFilterABTrim.hpp"
#include "Math/VoxImageFilterBilateral.hpp"
#include "Math/VoxImageFilterThreshold.hpp"
#include "Math/VoxImageFilterMedian.hpp"
#include "Math/VoxImageFilter2ndStat.hpp"
#include "Math/VoxImageFilterCustom.hpp"
namespace py = pybind11;
using namespace uLib;
template <typename Algorithm>
void bind_common_filter(py::class_<Algorithm, Abstract::VoxImageFilter> &cls) {
cls.def(py::init<const Vector3i &>())
.def("Run", &Algorithm::Run)
.def("SetKernelNumericXZY", &Algorithm::SetKernelNumericXZY)
.def("GetImage", &Algorithm::GetImage, py::return_value_policy::reference_internal)
.def("SetImage", &Algorithm::SetImage);
}
void init_math_filters(py::module_ &m) {
// Abstract::VoxImageFilter
py::class_<Abstract::VoxImageFilter, std::unique_ptr<Abstract::VoxImageFilter, py::nodelete>>(m, "AbstractVoxImageFilter")
.def("Run", &Abstract::VoxImageFilter::Run)
.def("SetImage", &Abstract::VoxImageFilter::SetImage);
// Helper macro to define standard bindings for a filter
#define BIND_FILTER(ClassName) \
{ \
auto cls = py::class_<ClassName<Voxel>, Abstract::VoxImageFilter>(m, #ClassName); \
bind_common_filter(cls); \
}
// VoxFilterAlgorithmLinear
{
auto cls = py::class_<VoxFilterAlgorithmLinear<Voxel>, Abstract::VoxImageFilter>(m, "VoxFilterAlgorithmLinear");
bind_common_filter(cls);
}
// VoxFilterAlgorithmAbtrim
{
auto cls = py::class_<VoxFilterAlgorithmAbtrim<Voxel>, Abstract::VoxImageFilter>(m, "VoxFilterAlgorithmAbtrim");
bind_common_filter(cls);
cls.def("SetABTrim", &VoxFilterAlgorithmAbtrim<Voxel>::SetABTrim);
}
// VoxFilterAlgorithmSPR
{
auto cls = py::class_<VoxFilterAlgorithmSPR<Voxel>, Abstract::VoxImageFilter>(m, "VoxFilterAlgorithmSPR");
bind_common_filter(cls);
cls.def("SetABTrim", &VoxFilterAlgorithmSPR<Voxel>::SetABTrim);
}
// VoxFilterAlgorithmBilateral
{
auto cls = py::class_<VoxFilterAlgorithmBilateral<Voxel>, Abstract::VoxImageFilter>(m, "VoxFilterAlgorithmBilateral");
bind_common_filter(cls);
cls.def("SetIntensitySigma", &VoxFilterAlgorithmBilateral<Voxel>::SetIntensitySigma);
}
// VoxFilterAlgorithmBilateralTrim
{
auto cls = py::class_<VoxFilterAlgorithmBilateralTrim<Voxel>, Abstract::VoxImageFilter>(m, "VoxFilterAlgorithmBilateralTrim");
bind_common_filter(cls);
cls.def("SetIntensitySigma", &VoxFilterAlgorithmBilateralTrim<Voxel>::SetIntensitySigma);
cls.def("SetABTrim", &VoxFilterAlgorithmBilateralTrim<Voxel>::SetABTrim);
}
// VoxFilterAlgorithmThreshold
{
auto cls = py::class_<VoxFilterAlgorithmThreshold<Voxel>, Abstract::VoxImageFilter>(m, "VoxFilterAlgorithmThreshold");
bind_common_filter(cls);
cls.def("SetThreshold", &VoxFilterAlgorithmThreshold<Voxel>::SetThreshold);
}
// VoxFilterAlgorithmMedian
{
auto cls = py::class_<VoxFilterAlgorithmMedian<Voxel>, Abstract::VoxImageFilter>(m, "VoxFilterAlgorithmMedian");
bind_common_filter(cls);
}
// VoxFilterAlgorithm2ndStat
{
auto cls = py::class_<VoxFilterAlgorithm2ndStat<Voxel>, Abstract::VoxImageFilter>(m, "VoxFilterAlgorithm2ndStat");
bind_common_filter(cls);
}
// VoxFilterAlgorithmCustom (Omit CustomEvaluate since it uses static function ptrs)
{
auto cls = py::class_<VoxFilterAlgorithmCustom<Voxel>, Abstract::VoxImageFilter>(m, "VoxFilterAlgorithmCustom");
bind_common_filter(cls);
}
}

20
src/Python/module.cpp Normal file
View File

@@ -0,0 +1,20 @@
#include <pybind11/pybind11.h>
namespace py = pybind11;
void init_core(py::module_ &m);
void init_math(py::module_ &m);
void init_math_filters(py::module_ &m);
PYBIND11_MODULE(uLib_python, m) {
m.doc() = "Python bindings for uLib Core and Math libraries";
// Core submodule
py::module_ core = m.def_submodule("Core", "Core library bindings");
init_core(core);
// Math submodule
py::module_ math = m.def_submodule("Math", "Math library bindings");
init_math(math);
init_math_filters(math);
}

View File

@@ -0,0 +1,33 @@
import sys
import os
import unittest
import time
import uLib
class TestCoreOptions(unittest.TestCase):
def test_options(self):
opt = uLib.Core.Options("Test Options")
# Test basic config file parsing
with open("test_configuration.ini", "w") as f:
f.write("[Section]\n")
opt.parse_config_file("test_configuration.ini")
os.remove("test_configuration.ini")
class TestCoreObject(unittest.TestCase):
def test_object(self):
obj = uLib.Core.Object()
self.assertIsNotNone(obj)
class TestCoreTimer(unittest.TestCase):
def test_timer(self):
timer = uLib.Core.Timer()
timer.Start()
time.sleep(0.1)
val = timer.StopWatch()
self.assertGreater(val, 0.09)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,151 @@
import unittest
import numpy as np
import os
import sys
# Ensure PYTHONPATH is correct if run from root
sys.path.append(os.path.join(os.getcwd(), 'src', 'Python'))
import uLib
class TestMathFilters(unittest.TestCase):
def test_filter_creation(self):
# 1. Linear Filter
dims = [10, 10, 10]
v_dims = uLib.Math.Vector3i(dims)
linear_filter = uLib.Math.VoxFilterAlgorithmLinear(v_dims)
self.assertIsNotNone(linear_filter)
# 2. ABTrim Filter
abtrim_filter = uLib.Math.VoxFilterAlgorithmAbtrim(v_dims)
self.assertIsNotNone(abtrim_filter)
abtrim_filter.SetABTrim(1, 1)
# 3. Bilateral Filter
bilat_filter = uLib.Math.VoxFilterAlgorithmBilateral(v_dims)
self.assertIsNotNone(bilat_filter)
bilat_filter.SetIntensitySigma(0.5)
# 4. Threshold Filter
threshold_filter = uLib.Math.VoxFilterAlgorithmThreshold(v_dims)
self.assertIsNotNone(threshold_filter)
threshold_filter.SetThreshold(0.5)
# 5. Median Filter
median_filter = uLib.Math.VoxFilterAlgorithmMedian(v_dims)
self.assertIsNotNone(median_filter)
def test_filter_run(self):
# Create image
dims = [10, 10, 10]
vox_img = uLib.Math.VoxImage(dims)
for i in range(10*10*10):
vox_img.SetValue(i, 1.0)
# Linear filter
linear_filter = uLib.Math.VoxFilterAlgorithmLinear([3, 3, 3])
linear_filter.SetImage(vox_img)
# Set kernel (simple 3x3x3 all ones)
# Weights are usually normalized in linear filter logic?
# Let's just test it runs.
linear_filter.SetKernelNumericXZY([1.0] * 27)
# Run filter
linear_filter.Run()
# Value should be 1.0 (mean of all 1.0 is 1.0)
self.assertAlmostEqual(vox_img.GetValue(0), 1.0)
def test_filter_run_abtrim(self):
# Create image
dims = [10, 10, 10]
vox_img = uLib.Math.VoxImage(dims)
for i in range(10*10*10):
vox_img.SetValue(i, 1.0)
# ABTrim filter
abtrim_filter = uLib.Math.VoxFilterAlgorithmAbtrim([3, 3, 3])
abtrim_filter.SetImage(vox_img)
# Set kernel (simple 3x3x3 all ones)
# Weights are usually normalized in linear filter logic?
# Let's just test it runs.
abtrim_filter.SetKernelNumericXZY([1.0] * 27)
# Run filter
abtrim_filter.Run()
# Value should be 1.0 (mean of all 1.0 is 1.0)
self.assertAlmostEqual(vox_img.GetValue(0), 1.0)
def test_filter_run_bilateral(self):
# Create image
dims = [10, 10, 10]
vox_img = uLib.Math.VoxImage(dims)
for i in range(10*10*10):
vox_img.SetValue(i, 1.0)
# Bilateral filter
bilat_filter = uLib.Math.VoxFilterAlgorithmBilateral([3, 3, 3])
bilat_filter.SetImage(vox_img)
# Set kernel (simple 3x3x3 all ones)
# Weights are usually normalized in linear filter logic?
# Let's just test it runs.
bilat_filter.SetKernelNumericXZY([1.0] * 27)
# Run filter
bilat_filter.Run()
# Value should be 1.0 (mean of all 1.0 is 1.0)
self.assertAlmostEqual(vox_img.GetValue(0), 1.0)
def test_filter_run_threshold(self):
# Create image
dims = [10, 10, 10]
vox_img = uLib.Math.VoxImage(dims)
for i in range(10*10*10):
vox_img.SetValue(i, 1.0)
# Threshold filter
threshold_filter = uLib.Math.VoxFilterAlgorithmThreshold([3, 3, 3])
threshold_filter.SetImage(vox_img)
# Set kernel (simple 3x3x3 all ones)
# Weights are usually normalized in linear filter logic?
# Let's just test it runs.
threshold_filter.SetKernelNumericXZY([1.0] * 27)
# Run filter
threshold_filter.Run()
# Value should be 1.0 (mean of all 1.0 is 1.0)
self.assertAlmostEqual(vox_img.GetValue(0), 1.0)
def test_filter_run_median(self):
# Create image
dims = [10, 10, 10]
vox_img = uLib.Math.VoxImage(dims)
for i in range(10*10*10):
vox_img.SetValue(i, 1.0)
# Median filter
median_filter = uLib.Math.VoxFilterAlgorithmMedian([3, 3, 3])
median_filter.SetImage(vox_img)
# Set kernel (simple 3x3x3 all ones)
# Weights are usually normalized in linear filter logic?
# Let's just test it runs.
median_filter.SetKernelNumericXZY([1.0] * 27)
# Run filter
median_filter.Run()
# Value should be 1.0 (mean of all 1.0 is 1.0)
self.assertAlmostEqual(vox_img.GetValue(0), 1.0)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,189 @@
import sys
import os
import unittest
import numpy as np
import uLib
def vector4f0(v, target):
diff = np.array(v) - np.array(target)
diff[3] = 0 # ignoring w
return np.all(np.abs(diff) < 0.001)
class TestMathMatrix(unittest.TestCase):
def test_matrix(self):
def check_1234(m2f):
self.assertEqual(m2f[0, 0], 1)
self.assertEqual(m2f[0, 1], 2)
self.assertEqual(m2f[1, 0], 3)
self.assertEqual(m2f[1, 1], 4)
m2f = uLib.Math.Matrix2f()
m2f[0, 0] = 1
m2f[0, 1] = 2
m2f[1, 0] = 3
m2f[1, 1] = 4
check_1234(m2f)
m2f = uLib.Math.Matrix2f([1, 2, 3, 4])
check_1234(m2f)
# m2f = uLib.Math.Matrix2f([[1, 2], [3, 4]])
# check_1234(m2f)
m2f = uLib.Math.Matrix2f(np.array([[1, 2], [3, 4]]))
check_1234(m2f)
def test_vector2(self):
v2f = uLib.Math.Vector2f()
v2f[0] = 1
v2f[1] = 2
self.assertEqual(v2f[0], 1)
self.assertEqual(v2f[1], 2)
v2f = uLib.Math.Vector2f([1, 2])
self.assertEqual(v2f[0], 1)
self.assertEqual(v2f[1], 2)
v2f = uLib.Math.Vector2f(np.array([1, 2]))
self.assertEqual(v2f[0], 1)
self.assertEqual(v2f[1], 2)
def test_vector3(self):
v3f = uLib.Math.Vector3f()
v3f[0] = 1
v3f[1] = 2
v3f[2] = 3
self.assertEqual(v3f[0], 1)
self.assertEqual(v3f[1], 2)
self.assertEqual(v3f[2], 3)
v3f = uLib.Math.Vector3f([1, 2, 3])
self.assertEqual(v3f[0], 1)
self.assertEqual(v3f[1], 2)
self.assertEqual(v3f[2], 3)
v3f = uLib.Math.Vector3f(np.array([1, 2, 3]))
self.assertEqual(v3f[0], 1)
self.assertEqual(v3f[1], 2)
self.assertEqual(v3f[2], 3)
class TestMathGeometry(unittest.TestCase):
def test_geometry(self):
Geo = uLib.Math.Geometry()
Geo.SetPosition([1, 1, 1])
pt = Geo.GetLocalPoint([2, 3, 2, 1])
wp = Geo.GetWorldPoint(pt)
self.assertTrue(vector4f0(wp, [2, 3, 2, 1]))
Geo.Scale([2, 2, 2])
wp = Geo.GetWorldPoint([1, 1, 1, 1])
self.assertTrue(vector4f0(wp, [3, 3, 3, 1]))
class TestMathContainerBox(unittest.TestCase):
def test_container_box_local(self):
Cnt = uLib.Math.ContainerBox()
Cnt.SetOrigin([-1, -1, -1])
Cnt.SetSize([2, 2, 2])
size = Cnt.GetSize()
self.assertTrue(np.allclose(size, [2, 2, 2]))
def test_container_box_global(self):
Box = uLib.Math.ContainerBox()
Box.SetPosition([1, 1, 1])
Box.SetSize([2, 2, 2])
pt = Box.GetLocalPoint([2, 3, 2, 1])
wp = Box.GetWorldPoint(pt)
self.assertTrue(vector4f0(wp, [2, 3, 2, 1]))
class TestMathStructuredGrid(unittest.TestCase):
def test_structured_grid(self):
grid = uLib.Math.StructuredGrid([10, 10, 10])
grid.SetSpacing([1, 1, 1])
spacing = grid.GetSpacing()
self.assertTrue(np.allclose(spacing, [1, 1, 1]))
class TestMathAccumulator(unittest.TestCase):
def test_accumulator_mean(self):
acc = uLib.Math.Accumulator_Mean_f()
acc(10.0)
acc(20.0)
self.assertAlmostEqual(acc(), 15.0)
class TestMathNewTypes(unittest.TestCase):
def test_eigen_vectors(self):
v1f = uLib.Math.Vector1f()
v3d = uLib.Math.Vector3d()
m4f = uLib.Math.Matrix4f()
self.assertIsNotNone(v1f)
self.assertIsNotNone(v3d)
self.assertIsNotNone(m4f)
def test_ulib_vectors(self):
vi = uLib.Math.Vector_i()
vi.append(1)
vi.append(2)
self.assertEqual(len(vi), 2)
self.assertEqual(vi[0], 1)
self.assertEqual(vi[1], 2)
vf = uLib.Math.Vector_f()
vf.append(1.5)
self.assertAlmostEqual(vf[0], 1.5)
def test_homogeneous(self):
p = uLib.Math.HPoint3f(1.0, 2.0, 3.0)
v = uLib.Math.HVector3f(0.0, 1.0, 0.0)
self.assertIsNotNone(p)
self.assertIsNotNone(v)
def test_vox_image(self):
img = uLib.Math.VoxImage([2, 2, 2])
self.assertEqual(img.GetDims()[0], 2)
img.SetValue([0, 0, 0], 10.5)
# Note: GetValue returns float, and there might be internal scaling (1.E-6 observed in code)
# Actually in VoxImage.h: GetValue(id) returns At(id).Value
# SetValue(id, value) sets At(id).Value = value
self.assertAlmostEqual(img.GetValue([0, 0, 0]), 10.5)
class TestMathVoxRaytracer(unittest.TestCase):
def test_raytracer(self):
grid = uLib.Math.StructuredGrid([10, 10, 10])
grid.SetSpacing([1, 1, 1])
grid.SetOrigin([0, 0, 0])
rt = uLib.Math.VoxRaytracer(grid)
self.assertIsNotNone(rt)
# Test TraceBetweenPoints
p1 = np.array([0.5, 0.5, -1.0, 1.0], dtype=np.float32)
p2 = np.array([0.5, 0.5, 11.0, 1.0], dtype=np.float32)
data = rt.TraceBetweenPoints(p1, p2)
self.assertGreater(data.Count(), 0)
self.assertAlmostEqual(data.TotalLength(), 10.0)
# Check elements
elements = data.Data()
for i in range(data.Count()):
self.assertGreaterEqual(elements[i].vox_id, 0)
self.assertGreater(elements[i].L, 0)
def test_ray_data(self):
data = uLib.Math.VoxRaytracerRayData()
data.SetCount(10)
data.SetTotalLength(5.5)
self.assertEqual(data.Count(), 10)
self.assertAlmostEqual(data.TotalLength(), 5.5)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,46 @@
import sys
import os
import uLib
def test_core():
print("Testing Core module...")
obj = uLib.Core.Object()
print("Core Object created:", obj)
timer = uLib.Core.Timer()
timer.Start()
print("Core Timer started")
options = uLib.Core.Options("Test Options")
print("Core Options created:", options)
def test_math():
print("Testing Math module...")
# Test AffineTransform
transform = uLib.Math.AffineTransform()
print("AffineTransform created")
# Test Geometry
geom = uLib.Math.Geometry()
print("Geometry created")
# Test StructuredData
data = uLib.Math.StructuredData([10, 10, 10])
print("StructuredData created with dims:", data.GetDims())
# Test Structured2DGrid
grid2d = uLib.Math.Structured2DGrid()
grid2d.SetDims([100, 100])
print("Structured2DGrid created with dims:", grid2d.GetDims())
# Test TriangleMesh
mesh = uLib.Math.TriangleMesh()
print("TriangleMesh created")
print("All tests passed successfully!")
if __name__ == "__main__":
test_core()
test_math()

View File

@@ -0,0 +1,7 @@
try:
from .uLib_python import Core, Math
except ImportError:
# Handle cases where the binary extension is not yet built
pass
__all__ = ["Core", "Math"]

View File

@@ -5,6 +5,8 @@ set(HEADERS RootMathDense.h
muCastorHit.h muCastorHit.h
muCastorInfo.h muCastorInfo.h
muCastorSkinHit.h muCastorSkinHit.h
muCastorPrimaryVertex.h
muCastorMuDetDIGI.h
SkinDetectorWriter.h) SkinDetectorWriter.h)
set(SOURCES ${HEADERS} RootMuonScatter.cpp set(SOURCES ${HEADERS} RootMuonScatter.cpp
@@ -12,12 +14,16 @@ set(SOURCES ${HEADERS} RootMuonScatter.cpp
muCastorHit.cpp muCastorHit.cpp
muCastorInfo.cpp muCastorInfo.cpp
muCastorSkinHit.cpp muCastorSkinHit.cpp
muCastorPrimaryVertex.cpp
muCastorMuDetDIGI.cpp
SkinDetectorWriter.cpp) SkinDetectorWriter.cpp)
set(DICTIONARY_HEADERS muCastorMCTrack.h set(DICTIONARY_HEADERS muCastorMCTrack.h
muCastorHit.h muCastorHit.h
muCastorInfo.h muCastorInfo.h
muCastorSkinHit.h muCastorSkinHit.h
muCastorPrimaryVertex.h
muCastorMuDetDIGI.h
SkinDetectorWriter.h) SkinDetectorWriter.h)
set(LIBRARIES ${ROOT_LIBRARIES} set(LIBRARIES ${ROOT_LIBRARIES}
@@ -36,7 +42,7 @@ list(APPEND SOURCES ${rDictName}.cxx)
set(R_ARTIFACTS ${CMAKE_CURRENT_BINARY_DIR}/lib${rDictName}_rdict.pcm set(R_ARTIFACTS ${CMAKE_CURRENT_BINARY_DIR}/lib${rDictName}_rdict.pcm
${CMAKE_CURRENT_BINARY_DIR}/lib${rDictName}.rootmap) ${CMAKE_CURRENT_BINARY_DIR}/lib${rDictName}.rootmap)
install(FILES ${R_ARTIFACTS} install(FILES ${R_ARTIFACTS}
DESTINATION ${PACKAGE_INSTALL_LIB_DIR}) DESTINATION ${INSTALL_LIB_DIR})
set(libname ${PACKAGE_LIBPREFIX}Root) set(libname ${PACKAGE_LIBPREFIX}Root)
set(ULIB_SHARED_LIBRARIES ${ULIB_SHARED_LIBRARIES} ${libname} PARENT_SCOPE) set(ULIB_SHARED_LIBRARIES ${ULIB_SHARED_LIBRARIES} ${libname} PARENT_SCOPE)
@@ -45,14 +51,18 @@ set(ULIB_SELECTED_MODULES ${ULIB_SELECTED_MODULES} Root PARENT_SCOPE)
add_library(${libname} SHARED ${SOURCES}) add_library(${libname} SHARED ${SOURCES})
set_target_properties(${libname} PROPERTIES set_target_properties(${libname} PROPERTIES
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_SOVERSION}) SOVERSION ${PROJECT_SOVERSION}
CXX_STANDARD 17)
target_link_libraries(${libname} ${LIBRARIES}) target_link_libraries(${libname} ${LIBRARIES})
install(TARGETS ${libname} install(TARGETS ${libname}
EXPORT "${PROJECT_NAME}Targets" EXPORT "${PROJECT_NAME}Targets"
RUNTIME DESTINATION ${PACKAGE_INSTALL_BIN_DIR} COMPONENT bin RUNTIME DESTINATION ${INSTALL_BIN_DIR} COMPONENT bin
LIBRARY DESTINATION ${PACKAGE_INSTALL_LIB_DIR} COMPONENT lib) LIBRARY DESTINATION ${INSTALL_LIB_DIR} COMPONENT lib)
install(FILES ${HEADERS} DESTINATION ${PACKAGE_INSTALL_INC_DIR}/Root)
install(FILES ${HEADERS} DESTINATION ${INSTALL_INC_DIR}/Root)
if(BUILD_TESTING)
include(uLibTargetMacros)
add_subdirectory(testing)
endif()

Some files were not shown because too many files have changed in this diff Show More