Skip to content

Commit 9381f75

Browse files
committed
[tmva][sofie] Disentangle PyMVA and SOFIE
So far, the part of SOFIE that uses the C Python API was included in PyMVA for convenience, but the functionality is completely unrelated. Moving this code to SOFIE itself means we can fully build and test SOFIE without enabling `tmva-pymva`. The only subtelty is that we want to be able to disable these SOFIE features that require linking against `libpython`, because this is not always allowed (e.g. in the Python wheels). Therefore, this part is only built if we build also the other ROOT libraries that links against `libpython` besides PyMVA, wich is `TPython`.
1 parent e08cce0 commit 9381f75

19 files changed

+161
-105
lines changed

cmake/modules/SearchInstalledSoftware.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ if(pyroot AND NOT (tpython OR tmva-pymva))
705705
elseif(tpython OR tmva-pymva)
706706
list(APPEND python_components Development)
707707
endif()
708-
if(tmva-pymva)
708+
if(tmva-pymva OR tmva-sofie)
709709
list(APPEND python_components NumPy)
710710
endif()
711711
find_package(Python3 3.9 COMPONENTS ${python_components})
@@ -1796,7 +1796,7 @@ if(tmva)
17961796
endif()
17971797
endif()
17981798
endif()
1799-
if(tmva-pymva)
1799+
if(tmva-pymva OR tmva-sofie)
18001800
if(fail-on-missing AND (NOT Python3_NumPy_FOUND OR NOT Python3_Development_FOUND))
18011801
message(SEND_ERROR "TMVA: numpy python package or Python development package not found and tmva-pymva component required"
18021802
" (python executable: ${Python3_EXECUTABLE})")

tmva/pymva/CMakeLists.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,13 @@ ROOT_STANDARD_LIBRARY_PACKAGE(PyMVA
1717
TMVA/MethodPyKeras.h
1818
TMVA/MethodPyRandomForest.h
1919
TMVA/MethodPyTorch.h
20-
TMVA/RModelParser_Keras.h
21-
TMVA/RModelParser_PyTorch.h
2220
TMVA/PyMethodBase.h
2321
SOURCES
2422
src/MethodPyAdaBoost.cxx
2523
src/MethodPyGTB.cxx
2624
src/MethodPyKeras.cxx
2725
src/MethodPyRandomForest.cxx
2826
src/MethodPyTorch.cxx
29-
src/RModelParser_Keras.cxx
30-
src/RModelParser_PyTorch.cxx
3127
src/PyMethodBase.cxx
3228
LIBRARIES
3329
Python3::NumPy
@@ -38,7 +34,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(PyMVA
3834
Thread
3935
RIO
4036
TMVA
41-
ROOTTMVASofie
4237
)
4338

4439
ROOT_ADD_TEST_SUBDIRECTORY(test)

tmva/pymva/inc/LinkDef.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,4 @@
1515
#pragma link C++ class TMVA::MethodPyGTB+;
1616
#pragma link C++ class TMVA::MethodPyKeras+;
1717
#pragma link C++ class TMVA::MethodPyTorch+;
18-
#pragma link C++ namespace TMVA::Experimental::SOFIE::PyKeras;
19-
#pragma link C++ function TMVA::Experimental::SOFIE::PyKeras::Parse+;
20-
#pragma link C++ namespace TMVA::Experimental::SOFIE::PyTorch;
21-
#pragma link C++ function TMVA::Experimental::SOFIE::PyTorch::Parse+;
2218
#endif

tmva/pymva/test/CMakeLists.txt

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
project(pymva-tests)
1313

14-
set(Libraries Core MathCore TMVA PyMVA ROOTTMVASofie)
14+
set(Libraries Core MathCore TMVA PyMVA)
1515

1616
# Look for needed python modules
1717
ROOT_FIND_PYTHON_MODULE(torch)
@@ -55,10 +55,6 @@ endif(ROOT_SKLEARN_FOUND)
5555

5656
# Enable tests based on available python modules
5757
if(ROOT_TORCH_FOUND)
58-
configure_file(generatePyTorchModelClassification.py generatePyTorchModelClassification.py COPYONLY)
59-
configure_file(generatePyTorchModelMulticlass.py generatePyTorchModelMulticlass.py COPYONLY)
60-
configure_file(generatePyTorchModelRegression.py generatePyTorchModelRegression.py COPYONLY)
61-
configure_file(generatePyTorchModels.py generatePyTorchModels.py COPYONLY)
6258
# Test PyTorch: Binary classification
6359

6460
if (ROOT_SKLEARN_FOUND)
@@ -80,27 +76,9 @@ if(ROOT_TORCH_FOUND)
8076
LIBRARIES ${Libraries})
8177
ROOT_ADD_TEST(PyMVA-Torch-Multiclass COMMAND testPyTorchMulticlass DEPENDS ${PyMVA-Torch-Multiclass-depends})
8278

83-
# Test RModelParser_PyTorch
84-
85-
if(BLAS_FOUND)
86-
ROOT_ADD_GTEST(TestRModelParserPyTorch TestRModelParserPyTorch.C
87-
LIBRARIES
88-
ROOTTMVASofie
89-
TMVA
90-
Python3::NumPy
91-
Python3::Python
92-
BLAS::BLAS
93-
INCLUDE_DIRS
94-
SYSTEM
95-
${CMAKE_CURRENT_BINARY_DIR}
96-
)
97-
endif()
98-
9979
endif(ROOT_TORCH_FOUND)
10080

10181
if((ROOT_KERAS_FOUND AND ROOT_THEANO_FOUND) OR (ROOT_KERAS_FOUND AND ROOT_TENSORFLOW_FOUND))
102-
configure_file(generateKerasModels.py generateKerasModels.py COPYONLY)
103-
configure_file(scale_by_2_op.hxx scale_by_2_op.hxx COPYONLY)
10482

10583
if (ROOT_TORCH_FOUND)
10684
set(PyMVA-Keras-Classification-depends PyMVA-Torch-Classification)
@@ -127,19 +105,4 @@ if((ROOT_KERAS_FOUND AND ROOT_THEANO_FOUND) OR (ROOT_KERAS_FOUND AND ROOT_TENSOR
127105
ROOT_EXECUTABLE(testPyKerasMulticlass testPyKerasMulticlass.C
128106
LIBRARIES ${Libraries})
129107
ROOT_ADD_TEST(PyMVA-Keras-Multiclass COMMAND testPyKerasMulticlass DEPENDS ${PyMVA-Keras-Multiclass-depends})
130-
131-
if(BLAS_FOUND)
132-
ROOT_ADD_GTEST(TestRModelParserKeras TestRModelParserKeras.C
133-
LIBRARIES
134-
ROOTTMVASofie
135-
PyMVA
136-
Python3::NumPy
137-
Python3::Python
138-
BLAS::BLAS
139-
INCLUDE_DIRS
140-
SYSTEM
141-
${CMAKE_CURRENT_BINARY_DIR}
142-
)
143-
endif()
144-
145108
endif()

tmva/sofie/test/CMakeLists.txt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ endif()
107107

108108
# Look for needed Python modules
109109
ROOT_FIND_PYTHON_MODULE(torch)
110+
ROOT_FIND_PYTHON_MODULE(keras)
111+
110112
if (ROOT_TORCH_FOUND)
111113
configure_file(Conv1dModelGenerator.py Conv1dModelGenerator.py COPYONLY)
112114
configure_file(Conv2dModelGenerator.py Conv2dModelGenerator.py COPYONLY)
@@ -127,6 +129,46 @@ if (ROOT_TORCH_FOUND)
127129
endif()
128130
endif()
129131

132+
# Any reatures that link against libpython are disabled if built with tpython=OFF
133+
if (tpython AND ROOT_TORCH_FOUND AND BLAS_FOUND)
134+
configure_file(generatePyTorchModelClassification.py generatePyTorchModelClassification.py COPYONLY)
135+
configure_file(generatePyTorchModelMulticlass.py generatePyTorchModelMulticlass.py COPYONLY)
136+
configure_file(generatePyTorchModelRegression.py generatePyTorchModelRegression.py COPYONLY)
137+
configure_file(generatePyTorchModels.py generatePyTorchModels.py COPYONLY)
138+
139+
# Test RModelParser_PyTorch
140+
ROOT_ADD_GTEST(TestRModelParserPyTorch TestRModelParserPyTorch.C
141+
LIBRARIES
142+
ROOTTMVASofie
143+
TMVA
144+
Python3::NumPy
145+
Python3::Python
146+
BLAS::BLAS
147+
INCLUDE_DIRS
148+
SYSTEM
149+
${CMAKE_CURRENT_BINARY_DIR}
150+
)
151+
endif()
152+
153+
154+
# Any reatures that link against libpython are disabled if built with tpython=OFF
155+
if (tpython AND ROOT_KERAS_FOUND AND BLAS_FOUND)
156+
configure_file(generateKerasModels.py generateKerasModels.py COPYONLY)
157+
configure_file(scale_by_2_op.hxx scale_by_2_op.hxx COPYONLY)
158+
159+
ROOT_ADD_GTEST(TestRModelParserKeras TestRModelParserKeras.C
160+
LIBRARIES
161+
ROOTTMVASofie
162+
Python3::NumPy
163+
Python3::Python
164+
BLAS::BLAS
165+
INCLUDE_DIRS
166+
SYSTEM
167+
${CMAKE_CURRENT_BINARY_DIR}
168+
)
169+
endif()
170+
171+
130172
ROOT_EXECUTABLE(emitGNN GNN/EmitGNN.cxx LIBRARIES ROOTTMVASofie)
131173
ROOT_ADD_TEST(tmva-sofie-EmitGNN COMMAND emitGNN)
132174

tmva/pymva/test/TestRModelParserKeras.C renamed to tmva/sofie/test/TestRModelParserKeras.C

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,22 @@
77

88
#include "TSystem.h"
99
#include "TMVA/RSofieReader.hxx"
10-
#include "TMVA/PyMethodBase.h"
1110

1211
constexpr float DEFAULT_TOLERANCE = 1e-6f;
1312

13+
namespace {
14+
15+
// Utility functions (taken from PyMethodBase in PyMVA)
16+
17+
const char *PyStringAsString(PyObject *string)
18+
{
19+
PyObject *encodedString = PyUnicode_AsUTF8String(string);
20+
const char *cstring = PyBytes_AsString(encodedString);
21+
return cstring;
22+
}
23+
24+
} // namespace
25+
1426
void GenerateModels() {
1527

1628
FILE* fKerasModels = fopen("generateKerasModels.py", "r");
@@ -529,7 +541,7 @@ TEST(RModel, CUSTOM_OP)
529541
// get input name for custom (it is output of one before last)
530542
PyRun_String("outputName = model.get_layer(index=len(model.layers)-2).output.name",Py_single_input,fGlobalNS,fLocalNS);
531543
PyObject *pOutputName = PyDict_GetItemString(fLocalNS, "outputName");
532-
std::string outputName = TMVA::PyMethodBase::PyStringAsString(pOutputName);
544+
std::string outputName = PyStringAsString(pOutputName);
533545
TMVA::Experimental:: RSofieReader r;
534546
r.AddCustomOperator(/*OpName*/ "Scale_by_2",
535547
/*input tensor names where to insert custom op */std::string("{\"" + outputName + "\"}"),
@@ -550,4 +562,4 @@ TEST(RModel, CUSTOM_OP)
550562
for (size_t i = 0; i < outputCustomOp.size(); ++i) {
551563
EXPECT_LE(std::abs(outputCustomOp[i] - pOutputCustomOp[i]), TOLERANCE);
552564
}
553-
}
565+
}
File renamed without changes.

0 commit comments

Comments
 (0)