Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7956e87
adding python subdirectory
EdAtkin Sep 19, 2025
e1ff941
initial commit of some changes to the python build (not tested!)
EdAtkin Oct 1, 2025
e624bb7
adding stuff to the MaCh3 setup to automatically add pyMaCh3 to the p…
EdAtkin Oct 22, 2025
533dd02
Updating the build for the python bindings
EdAtkin Oct 22, 2025
074eaff
Adding a juptyer notebook giving examples of how to use the pyMaCh3 p…
EdAtkin Oct 23, 2025
ba86380
slight tweak to CMake build to properly set the MaCh3_PREFIX i.e. whe…
EdAtkin Oct 23, 2025
1f379d1
update to develop
ewanwm Feb 27, 2026
325db63
add full path when exporting header files
ewanwm Feb 27, 2026
8fa1f55
update python cmake to use new setup_pyMaCh3 function
ewanwm Feb 27, 2026
175bd8a
update binding to use new system
ewanwm Feb 27, 2026
693a390
tutorial sample handler now lives in samples module instead of making…
ewanwm Mar 10, 2026
01dfa16
*much* simpler import
ewanwm Mar 10, 2026
4d13ab0
no longer set target name
ewanwm Mar 10, 2026
7ce539c
add pyproject toml for pip installation
ewanwm Mar 10, 2026
930a941
set whether to install pyMaCh3 for tutorial in cmake
ewanwm Mar 10, 2026
0668551
add python enabled option in pyproject toml
ewanwm Mar 10, 2026
e099327
don't use the python enabled when building core
ewanwm Mar 25, 2026
ea3af62
fix inheritance of samplehandlerTutorial binding
ewanwm Mar 27, 2026
70e0869
remove depracated root syntax
ewanwm Mar 30, 2026
14f7c84
make version a dynamic variable in pyproject
ewanwm Mar 30, 2026
834e54a
remove manual MaCh3 core branch setting
ewanwm Mar 30, 2026
72a0f83
remove manual pythonpath setup from setup bash script
ewanwm Mar 30, 2026
04a9b1d
Add README file for existing python tests
ewanwm Mar 30, 2026
684879c
use include the pyMaCh3_tutorial module instead of just pyMach3
ewanwm Mar 30, 2026
11ce932
add test to check binding of c++ tutorial code
ewanwm Mar 30, 2026
f004d21
add pyMaCh3example.py (basically same as existing notebook but as script
ewanwm Mar 30, 2026
43f4717
Merge branch 'main' into feature_python_build
ewanwm Mar 30, 2026
cded8ce
add optional [test] pip build, make version automatically set, make p…
ewanwm Mar 30, 2026
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
9 changes: 9 additions & 0 deletions CIValidations/PythonTests/pure_python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Pure Python Extension Tests

These tests check extending the core MaCh3 code in pure python.

Current tests are:

* test_fitter_sample_pdf.py - creates a sample handler written in pure python, instantiates it, along with manager and parameterHandler, then runs short mcmc fit with it
* test_fitter_stat_only.pdf - runs stat only mcmc and minuit fits with ParameterHandlerGeneric instance
* test_splines.py - tests the splinehandler class and the interpolation functions
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
## MaCh3 imports
import pyMaCh3
from pyMaCh3 import samples
from pyMaCh3 import splines
from pyMaCh3 import fitters
from pyMaCh3 import manager
from pyMaCh3 import parameters
from pyMaCh3_tutorial import samples
from pyMaCh3_tutorial import splines
from pyMaCh3_tutorial import fitters
from pyMaCh3_tutorial import manager
from pyMaCh3_tutorial import parameters

## ROOT imports
import ROOT
Expand Down Expand Up @@ -62,7 +61,7 @@ def setup_splines(self, file_name: str) -> None:

## Open up the file and get the sample_sum tree from it
spline_file: TFile = TFile(file_name)
sample_sum: TTree = spline_file.sample_sum
sample_sum: TTree = spline_file["sample_sum"]

print(sample_sum.Print())

Expand Down Expand Up @@ -119,7 +118,7 @@ def setup_MC(self, file_name: str) -> None:
# Open up the input file and read in the event information from them
# (currently this means just the number of events as input has no kinematic parameters)
spline_file: TFile = TFile(file_name)
sample_sum: TTree = spline_file.sample_sum
sample_sum: TTree = spline_file["sample_sum"]

self.n_mc_events = sample_sum.GetEntries()
self.event_weights = np.ones((self.n_mc_events))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
"""

# MaCh3 includes
import pyMaCh3
from pyMaCh3 import fitters
from pyMaCh3 import manager
from pyMaCh3 import parameters
from pyMaCh3_tutorial import fitters
from pyMaCh3_tutorial import manager
from pyMaCh3_tutorial import parameters
# other python includes
import sys
import pytest
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Mach3 inputs
import pyMaCh3
from pyMaCh3 import splines
from pyMaCh3_tutorial import splines
# Other python includes
import numpy as np

Expand Down
7 changes: 7 additions & 0 deletions CIValidations/PythonTests/tutorial_bindings/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Python Binding Tests

These tests are intended to test the python binding of experiment specific c++ code.

Current tests are:

* test_tutorial_sample_handler.py - Tests the binding of the SampleHandlerTutorial class
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import os

# Now import pyMaCh3
from pyMaCh3_tutorial import parameters
from pyMaCh3_tutorial import samples

import pytest

print(f'MaCh3_ROOT env var: {os.environ["MaCh3_ROOT"]}')

def test_tutorial_sample_handler(pytestconfig):

# Create a parameter handler object from the SystematicModel.yaml file
parameter_handler = parameters.ParameterHandlerGeneric(["TutorialConfigs/CovObjs/SystematicModel.yaml", "TutorialConfigs/CovObjs/OscillationModel.yaml"])

# create the samplehandler object
sample_handler = samples.SampleHandlerTutorial("TutorialConfigs/Samples/SampleHandler_Tutorial.yaml", parameter_handler)

# now try reweighting and getting the weighted histogram
sample_handler.reweight()
mc_prediction, bin_edges_x, bin_edges_y = sample_handler.get_mc_hist(0)
data, bin_edges_x, bin_edges_y = sample_handler.get_data_hist(0)
50 changes: 46 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ option(MaCh3Tutorial_PROFILING_ENABLED "Will run with gperftools" OFF)
option(Use_External_MaCh3 "Use an externally installed MaCh3 instead of CPM" OFF)
option(MaCh3Tutorial_DEBUG_ENABLED "Use debug options" OFF)
option(MaCh3Tutorial_LOW_MEMORY_STRUCTS_ENABLED "Use floats" OFF)
option(PYTHON_ENABLED "Build python package" OFF)

# KS: Here we try to find tag matching tutorial version. If we can't find one then use develop
# This will allow to grab tutorial for tagged MaCh3 version without a need of manually changing version
Expand Down Expand Up @@ -75,10 +76,6 @@ if(NOT MaCh3_FOUND)
message(STATUS "MaCh3 is not found locally!")
set(MaCh3_OPTIONS "")

if(PYTHON_ENABLED)
list(APPEND MaCh3_OPTIONS "MaCh3_PYTHON_ENABLED ${PYTHON_ENABLED}")
endif()

# KS: For benchmark we turn off logger to not interfere with output messages.
# Also to have code compile let's turn off Werror
if (MaCh3Tutorial_Benchmark_ENABLED)
Expand Down Expand Up @@ -146,6 +143,51 @@ add_subdirectory(Tutorial)
add_subdirectory(SplinesTutorial)
add_subdirectory(SamplesTutorial)

# MOVE THIS BLOCK HERE - BEFORE add_subdirectory(python)
# After MaCh3 is added/found, determine MaCh3_PREFIX
if(NOT DEFINED MaCh3_PREFIX OR MaCh3_PREFIX STREQUAL "")
# Try to detect if MaCh3 was fetched by CPM
if(EXISTS "${CMAKE_BINARY_DIR}/_deps/mach3-src")
set(MaCh3_PREFIX "${CMAKE_BINARY_DIR}/_deps/mach3-src")
cmessage(STATUS "Detected CPM-fetched MaCh3: ${MaCh3_PREFIX}")
# Try to get from MaCh3 package config
elseif(DEFINED MaCh3_DIR)
get_filename_component(MaCh3_PREFIX "${MaCh3_DIR}" DIRECTORY)
get_filename_component(MaCh3_PREFIX "${MaCh3_PREFIX}" DIRECTORY)
cmessage(STATUS "Detected installed MaCh3 from MaCh3_DIR: ${MaCh3_PREFIX}")
# Try to get from target properties
elseif(TARGET MaCh3::All)
get_target_property(MACH3_INCLUDE_DIRS MaCh3::All INTERFACE_INCLUDE_DIRECTORIES)
if(MACH3_INCLUDE_DIRS)
list(GET MACH3_INCLUDE_DIRS 0 FIRST_INCLUDE_DIR)
get_filename_component(MaCh3_PREFIX "${FIRST_INCLUDE_DIR}" DIRECTORY)
cmessage(STATUS "Detected MaCh3 from target include dirs: ${MaCh3_PREFIX}")
endif()
endif()

# Final validation
if(NOT DEFINED MaCh3_PREFIX OR MaCh3_PREFIX STREQUAL "")
cmessage(FATAL_ERROR "Could not determine MaCh3_PREFIX. Please set it manually with -DMaCh3_PREFIX=<path>")
endif()

if(NOT EXISTS "${MaCh3_PREFIX}")
cmessage(FATAL_ERROR "MaCh3_PREFIX does not exist: ${MaCh3_PREFIX}")
endif()

# Cache it for use in subdirectories
set(MaCh3_PREFIX "${MaCh3_PREFIX}" CACHE PATH "MaCh3 installation or source directory" FORCE)
cmessage(STATUS "Set MaCh3_PREFIX: ${MaCh3_PREFIX}")
endif()

# NOW add the python subdirectory - MaCh3_PREFIX is already set
if(PYTHON_ENABLED)
cmessage(STATUS "PYTHON IS ENABLED!!")
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
cmessage(STATUS "CMAKE_INSTALL_RPATH is ${CMAKE_INSTALL_RPATH}")
set(PYMACH3_PATH ${CMAKE_BINARY_DIR}/python/pyMaCh3)
add_subdirectory(python)
endif()

configure_file(cmake/Templates/setup.MaCh3Tutorial.sh.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/setup.MaCh3Tutorial.sh" @ONLY)
install(FILES "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/setup.MaCh3Tutorial.sh" DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)

Expand Down
4 changes: 2 additions & 2 deletions SamplesTutorial/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
set(HEADERS
SampleHandlerTutorial.h
StructsTutorial.h
${CMAKE_CURRENT_SOURCE_DIR}/SampleHandlerTutorial.h
${CMAKE_CURRENT_SOURCE_DIR}/StructsTutorial.h
)

add_library(SamplesTutorial SHARED
Expand Down
2 changes: 1 addition & 1 deletion SplinesTutorial/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set(HEADERS BinnedSplinesTutorial.h
set(HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/BinnedSplinesTutorial.h
)

add_library(BinnedSplinesTutorial SHARED
Expand Down
27 changes: 27 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[build-system]
requires = ["scikit-build-core", "pybind11"]
build-backend = "scikit_build_core.build"

[project]
name = "pyMaCh3_tutorial"

dynamic = ["version", "dependencies"]

authors = [{ name = "The MaCh3 Collaboration" }]

[tool.setuptools.dynamic]
dependencies = {file = ["requirements.txt"]}

[project.optional-dependencies]
testing = [
"pytest"
]

[tool.scikit-build]
wheel.install-dir = "pyMaCh3_tutorial"

[tool.scikit-build.cmake]
args = ["-DPYTHON_ENABLED=ON"]

[tool.scikit-build.metadata.version]
provider = "scikit_build_core.metadata.setuptools_scm"
10 changes: 10 additions & 0 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

include(${MaCh3_PREFIX}/cmake/Modules/pyMaCh3.cmake)

setup_pyMaCh3(
INSTALL_DIR "NONE"
BINDING_FILES pyMaCh3.cpp
LINK_TARGETS
BinnedSplinesTutorial
SamplesTutorial
)
Loading
Loading