Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ test.py
cuda-*
wheelhouse
test.ipynb
venv/
venv/
.venv/
**.so
__pycache__/
14 changes: 10 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
cmake_minimum_required(VERSION 3.25.2)

project(rayx-python)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Install prefix" FORCE)
endif()

project(rayx-python)
add_subdirectory(extern)
add_subdirectory(src)

# create __init__.py and install it in INSTALL_DIR/rayxdata
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/__init__.py" "")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/__init__.py" DESTINATION "rayxdata")
# Install Python package
install(DIRECTORY python/rayx DESTINATION .)

# Create and install rayxdata package (needed by C++ code)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/rayxdata/__init__.py" "")
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/rayxdata" DESTINATION .)
16 changes: 15 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,32 @@ version = "0.4.1"
description = "Python bindings for RAYX"
readme = "README.md"
license = { file = "LICENSE" }

dependencies = ["numpy >= 2.0.0"]
requires-python = ">=3.7"
authors = [{ name = "RAYX team", email = "rayx-support@helmholtz-berlin.de" }]
maintainers = [
{ name = "RAYX team", email = "rayx-support@helmholtz-berlin.de" },
]

[project.optional-dependencies]
dev = [
"pytest>=7.0",
"matplotlib>=3.5",
"ipython",
]
test = [
"pytest>=7.0",
"pytest-cov",
]

[build-system]
requires = ["scikit-build-core", "pybind11"]
build-backend = "scikit_build_core.build"

[tool.scikit-build]
wheel.packages = ["python/rayx"]
cmake.build-type = "Release"

[tool.cibuildwheel]
archs = ["x86_64"]
build = ["*manylinux*"]
Expand Down
46 changes: 46 additions & 0 deletions python/rayx/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""
RAY-X Python bindings
"""
import sys
from pathlib import Path

# Import the C++ extension module
try:
from . import _core
except ImportError:
# During development, try to find the built module
import os
build_dir = Path(__file__).parent.parent.parent / "build" / "install" / "rayx"
if build_dir.exists():
sys.path.insert(0, str(build_dir.parent))
from rayx import _core
else:
raise ImportError("Cannot find compiled _core module. Did you build the project?")

# Re-export everything from C++ module
from ._core import *

# Add Python enhancements
def hello():
"""Test function to verify Python wrapper is included"""
return "Hello from Python wrapper!"

def get_info():
"""Get information about the RAYX installation"""
info = {
"version": __version__,
"python_wrapper": True,
"cpp_module": str(_core.__file__),
"module_path": str(Path(__file__).parent),
}
return info

def enhanced_function():
"""Pure Python function using C++ backend"""
# This is a placeholder - customize based on your actual C++ functions
# result = _core.cpp_function() # Call C++ function
# Add Python processing
return "Enhanced function - add your logic here"

__version__ = "0.4.1"
__all__ = ['hello', 'get_info', 'enhanced_function']
59 changes: 59 additions & 0 deletions setup_dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/bin/bash
# setup_dev.sh - Development setup with virtual environment

set -e

# Ensure we're in the right directory
cd "$(dirname "$0")"

# Check if venv exists
if [ ! -d ".venv" ]; then
echo "Creating virtual environment with uv..."
uv venv
source .venv/bin/activate
echo "Installing dependencies..."
uv pip install numpy pytest matplotlib
else
source .venv/bin/activate
fi

# Build C++ extension
echo "Building C++ extension..."
mkdir -p build
cd build

# Configure with local install prefix
cmake -DCMAKE_INSTALL_PREFIX=./install ..

# Build
make -j$(nproc)

# Install to local directory
make install

cd ..

# Create symlink
BUILD_DIR="build/install/rayx"
PYTHON_DIR="python/rayx"

SO_FILE=$(find "$BUILD_DIR" -name "_core.cpython-*.so" 2>/dev/null | head -n 1)

if [ -f "$SO_FILE" ]; then
ln -sf "../../$SO_FILE" "$PYTHON_DIR/_core.so"
echo "✓ Created symlink: $PYTHON_DIR/_core.so"
else
echo "✗ Error: Could not find _core.cpython-*.so in $BUILD_DIR"
echo "Files in build/install:"
find build/install -type f 2>/dev/null || echo " (directory doesn't exist)"
exit 1
fi

# Add python directory to PYTHONPATH for development
export PYTHONPATH="$(pwd)/python:$PYTHONPATH"

echo "✓ Development environment ready!"
echo ""
echo "To use:"
echo " source .venv/bin/activate"
echo " cd python && python3 -c 'import rayx; print(rayx.__version__)'"
15 changes: 8 additions & 7 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
project(rayxpy LANGUAGES CXX CUDA)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CUDA_STANDARD 20)
set(CMAKE_CUDA_STANDARD_REQUIRED ON)

set(PYBIND11_FINDPYTHON ON)

set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF)

pybind11_add_module(rayx main.cpp)
target_link_libraries(rayx PRIVATE rayx-core)
target_include_directories(rayx PRIVATE $<TARGET_PROPERTY:rayx-core,INTERFACE_INCLUDE_DIRECTORIES> ${CUDA_TOOLKIT_INCLUDE}/cccl)
# Changed from 'rayx' to '_core' to make it a private module
pybind11_add_module(_core main.cpp)
target_link_libraries(_core PRIVATE rayx-core)
target_include_directories(_core PRIVATE
$<TARGET_PROPERTY:rayx-core,INTERFACE_INCLUDE_DIRECTORIES>
${CUDA_TOOLKIT_INCLUDE}/cccl)

install(TARGETS rayx DESTINATION .)
# Install to rayx/ subdirectory
install(TARGETS _core LIBRARY DESTINATION rayx)
4 changes: 2 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ class Module {
}
};

PYBIND11_MODULE(rayx, m) {
PYBIND11_MODULE(_core, m) {
static Module module_instance;

m.doc() = "rayx module";
Expand Down Expand Up @@ -483,4 +483,4 @@ PYBIND11_MODULE(rayx, m) {

m.def(
"import_beamline", [](std::string path) { return rayx::importBeamline(path); }, "Import a beamline from an RML file", pybind11::arg("path"));
}
}