Skip to content

Commit 2462ca6

Browse files
committed
Module to call sourcex from Python
1 parent b0109e5 commit 2462ca6

File tree

31 files changed

+1709
-40
lines changed

31 files changed

+1709
-40
lines changed

SEFramework/SEFramework/Output/OutputRegistry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ class OutputRegistry {
177177
m_output_properties.emplace(alias_name, typeid(PropertyType));
178178
}
179179

180-
std::set<std::string> getOutputPropertyNames() {
180+
std::set<std::string> getOutputPropertyNames() const {
181181
std::set<std::string> result {};
182182
for (auto& pair : m_output_properties) {
183183
result.emplace(pair.first);

SEImplementation/SEImplementation/Configuration/PythonConfig.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
/** Copyright © 2019 Université de Genève, LMU Munich - Faculty of Physics, IAP-CNRS/Sorbonne Université
1+
/*
2+
* Copyright © 2019-2022 Université de Genève, LMU Munich - Faculty of Physics, IAP-CNRS/Sorbonne Université
23
*
34
* This library is free software; you can redistribute it and/or modify it under
45
* the terms of the GNU Lesser General Public License as published by the Free
@@ -41,6 +42,8 @@ class PythonConfig : public Euclid::Configuration::Configuration {
4142

4243
PythonInterpreter& getInterpreter() const;
4344

45+
private:
46+
boost::python::object m_measurement_config;
4447
};
4548

4649
}

SEImplementation/SEImplementation/PythonConfig/PythonInterpreter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class PythonInterpreter {
4141

4242
void runFile(const std::string& filename, const std::vector<std::string>& argv);
4343

44-
void setupContext();
44+
void setupContext(boost::python::object config = {});
4545

4646
virtual ~PythonInterpreter();
4747

SEImplementation/src/lib/Configuration/PythonConfig.cpp

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,25 @@
1515
* along with this library; if not, write to the Free Software Foundation, Inc.,
1616
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1717
*/
18-
/*
18+
/*
1919
* @file PythonConfig.cpp
2020
* @author Nikolaos Apostolakos <nikoapos@gmail.com>
2121
*/
2222

23-
#include <boost/filesystem.hpp>
2423
#include <SEImplementation/Configuration/PythonConfig.h>
24+
#include <boost/filesystem.hpp>
2525

2626
using namespace Euclid::Configuration;
2727
namespace po = boost::program_options;
2828
namespace fs = boost::filesystem;
2929

3030
namespace {
3131

32-
const std::string PYTHON_CONFIG_FILE { "python-config-file" };
33-
const std::string PYTHON_ARGV { "python-arg" };
32+
const std::string PYTHON_CONFIG_FILE{"python-config-file"};
33+
const std::string PYTHON_ARGV{"python-arg"};
34+
const std::string PYTHON_CONFIG_OBJ{"python-config-object"};
3435

35-
}
36+
} // namespace
3637

3738
namespace SourceXtractor {
3839

@@ -41,38 +42,43 @@ PythonConfig::PythonConfig(long manager_id) : Configuration(manager_id) {
4142
}
4243

4344
std::map<std::string, Configuration::OptionDescriptionList> PythonConfig::getProgramOptions() {
44-
return {{"Measurement config", {
45-
{PYTHON_CONFIG_FILE.c_str(), po::value<std::string>()->default_value({}, ""),
46-
"Measurements python configuration file"},
47-
{PYTHON_ARGV.c_str(), po::value<std::vector<std::string>>()->multitoken(),
48-
"Parameters to pass to Python via sys.argv"}
49-
}}};
45+
return {{"Measurement config",
46+
{{PYTHON_CONFIG_FILE.c_str(), po::value<std::string>()->default_value({}, ""),
47+
"Measurements python configuration file"},
48+
{PYTHON_ARGV.c_str(), po::value<std::vector<std::string>>()->multitoken(),
49+
"Parameters to pass to Python via sys.argv"}}}};
5050
}
5151

52-
5352
void PythonConfig::preInitialize(const UserValues& args) {
54-
auto filename = args.find(PYTHON_CONFIG_FILE)->second.as<std::string>();
55-
if (!filename.empty() && !fs::exists(filename)) {
56-
throw Elements::Exception() << "Python configuration file " << filename
57-
<< " does not exist";
53+
auto filename = args.find(PYTHON_CONFIG_FILE)->second.as<std::string>();
54+
auto py_obj_iter = args.find(PYTHON_CONFIG_OBJ);
55+
56+
if (py_obj_iter != args.end()) {
57+
m_measurement_config = py_obj_iter->second.as<boost::python::object>();
58+
} else if (!filename.empty() && !fs::exists(filename)) {
59+
throw Elements::Exception() << "Python configuration file " << filename << " does not exist";
5860
}
5961
}
6062

6163
void PythonConfig::initialize(const UserValues& args) {
62-
auto &singleton = PythonInterpreter::getSingleton();
63-
auto filename = args.find(PYTHON_CONFIG_FILE)->second.as<std::string>();
64-
if (!filename.empty()) {
65-
std::vector<std::string> argv;
66-
if (args.find(PYTHON_ARGV) != args.end()) {
67-
argv = args.find(PYTHON_ARGV)->second.as<std::vector<std::string>>();
64+
auto& singleton = PythonInterpreter::getSingleton();
65+
if (m_measurement_config) {
66+
singleton.setupContext(m_measurement_config);
67+
} else {
68+
auto filename = args.find(PYTHON_CONFIG_FILE)->second.as<std::string>();
69+
if (!filename.empty()) {
70+
std::vector<std::string> argv;
71+
if (args.find(PYTHON_ARGV) != args.end()) {
72+
argv = args.find(PYTHON_ARGV)->second.as<std::vector<std::string>>();
73+
}
74+
singleton.runFile(filename, argv);
6875
}
69-
singleton.runFile(filename, argv);
7076
}
71-
singleton.setupContext();
77+
singleton.setupContext(m_measurement_config);
7278
}
7379

7480
PythonInterpreter& PythonConfig::getInterpreter() const {
7581
return PythonInterpreter::getSingleton();
7682
}
7783

78-
} // end of namespace SourceXtractor
84+
} // end of namespace SourceXtractor

SEImplementation/src/lib/Plugin/DetectionFramePixelValues/DetectionFramePixelValuesPlugin.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
/** Copyright © 2019 Université de Genève, LMU Munich - Faculty of Physics, IAP-CNRS/Sorbonne Université
1+
/*
2+
* Copyright © 2019-2022 Université de Genève, LMU Munich - Faculty of Physics, IAP-CNRS/Sorbonne Université
23
*
34
* This library is free software; you can redistribute it and/or modify it under
45
* the terms of the GNU Lesser General Public License as published by the Free
@@ -21,24 +22,25 @@
2122
* Author: mschefer
2223
*/
2324

25+
#include "SEImplementation/Plugin/DetectionFramePixelValues/DetectionFramePixelValuesPlugin.h"
2426
#include "SEFramework/Plugin/StaticPlugin.h"
25-
2627
#include "SEImplementation/Plugin/DetectionFramePixelValues/DetectionFramePixelValues.h"
2728
#include "SEImplementation/Plugin/DetectionFramePixelValues/DetectionFramePixelValuesTaskFactory.h"
2829

29-
#include "SEImplementation/Plugin/DetectionFramePixelValues/DetectionFramePixelValuesPlugin.h"
30-
3130
namespace SourceXtractor {
3231

3332
static StaticPlugin<DetectionFramePixelValuesPlugin> detection_frame_pixel_values_plugin;
3433

3534
void DetectionFramePixelValuesPlugin::registerPlugin(PluginAPI& plugin_api) {
36-
plugin_api.getTaskFactoryRegistry().registerTaskFactory<DetectionFramePixelValuesTaskFactory, DetectionFramePixelValues>();
35+
auto& output_registry = plugin_api.getOutputRegistry();
36+
output_registry.registerColumnConverter<DetectionFramePixelValues, std::vector<DetectionImage::PixelType>>(
37+
"detection_pixel_values", [](const DetectionFramePixelValues& pixels) { return pixels.getValues(); });
38+
plugin_api.getTaskFactoryRegistry()
39+
.registerTaskFactory<DetectionFramePixelValuesTaskFactory, DetectionFramePixelValues>();
3740
}
3841

3942
std::string DetectionFramePixelValuesPlugin::getIdString() const {
4043
return "";
4144
}
4245

43-
}
44-
46+
} // namespace SourceXtractor

SEImplementation/src/lib/Plugin/FlexibleModelFitting/FlexibleModelFittingTaskFactory.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
/** Copyright © 2019 Université de Genève, LMU Munich - Faculty of Physics, IAP-CNRS/Sorbonne Université
1+
/*
2+
* Copyright © 2019-2022 Université de Genève, LMU Munich - Faculty of Physics, IAP-CNRS/Sorbonne Université
23
*
34
* This library is free software; you can redistribute it and/or modify it under
45
* the terms of the GNU Lesser General Public License as published by the Free
@@ -51,6 +52,7 @@ std::shared_ptr<Task> FlexibleModelFittingTaskFactory::createTask(const Property
5152

5253
void FlexibleModelFittingTaskFactory::reportConfigDependencies(Euclid::Configuration::ConfigManager& manager) const {
5354
manager.registerConfiguration<ModelFittingConfig>();
55+
manager.registerConfiguration<SamplingConfig>();
5456
}
5557

5658
void FlexibleModelFittingTaskFactory::configure(Euclid::Configuration::ConfigManager& manager) {

SEImplementation/src/lib/PythonConfig/PythonInterpreter.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ PythonInterpreter& PythonInterpreter::getSingleton() {
5050
}
5151

5252
PythonInterpreter::PythonInterpreter() : m_out_wrapper(stdout_logger), m_err_wrapper(stderr_logger) {
53+
// We may be called *from* Python!
54+
if (Py_IsInitialized()) {
55+
return;
56+
}
5357
// Python sets its own signal handler for SIGINT (Ctrl+C), so it can throw a KeyboardInterrupt
5458
// Here we are not interested on this behaviour, so we get whatever handler we've got (normally
5559
// the default one) and restore it after initializing the interpreter
@@ -121,10 +125,14 @@ void PythonInterpreter::runFile(const std::string& filename, const std::vector<s
121125
}
122126
}
123127

124-
void PythonInterpreter::setupContext() {
128+
void PythonInterpreter::setupContext(boost::python::object config) {
125129
Pyston::GILLocker locker;
126130
try {
127-
m_measurement_config = py::import("sourcextractor.config.measurement_config").attr("global_measurement_config");
131+
if (config) {
132+
m_measurement_config = config;
133+
} else {
134+
m_measurement_config = py::import("sourcextractor.config.measurement_config").attr("global_measurement_config");
135+
}
128136
} catch (const py::error_already_set& e) {
129137
throw Pyston::Exception().log(log4cpp::Priority::ERROR, logger);
130138
}

SEMain/src/program/SourceXtractor.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@
7373
#include "SEImplementation/Configuration/WeightImageConfig.h"
7474
#include "SEImplementation/Configuration/MemoryConfig.h"
7575
#include "SEImplementation/Configuration/OutputConfig.h"
76-
#include "SEImplementation/Configuration/SamplingConfig.h"
7776
#include "SEImplementation/CheckImages/CheckImages.h"
7877
#include "SEImplementation/Prefetcher/Prefetcher.h"
7978

@@ -189,7 +188,6 @@ class SEMain : public Elements::Program {
189188
config_manager.registerConfiguration<SE2BackgroundConfig>();
190189
config_manager.registerConfiguration<MemoryConfig>();
191190
config_manager.registerConfiguration<BackgroundAnalyzerFactory>();
192-
config_manager.registerConfiguration<SamplingConfig>();
193191
config_manager.registerConfiguration<DetectionFrameConfig>();
194192

195193
CheckImages::getInstance().reportConfigDependencies(config_manager);

SEPythonModule/CMakeLists.txt

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)
2+
3+
#===============================================================================
4+
# Load elements_subdir macro here
5+
# Examples:
6+
# For declaring a project module:
7+
# elements_subdir(ElementsExamples)
8+
#===============================================================================
9+
elements_subdir(SEPythonModule)
10+
11+
#===============================================================================
12+
# Load elements_depends_on_subdirs macro here
13+
# For creating a dependency onto an other accessible module
14+
# elements_depends_on_subdirs(ElementsKernel)
15+
#===============================================================================
16+
elements_depends_on_subdirs(ElementsKernel)
17+
elements_depends_on_subdirs(SEImplementation)
18+
elements_depends_on_subdirs(SEMain)
19+
20+
#===============================================================================
21+
# Add the find_package macro (a pure CMake command) here to locate the
22+
# libraries.
23+
# Examples:
24+
# find_package(CppUnit)
25+
#===============================================================================
26+
find_package(PythonInterp ${PYTHON_EXPLICIT_VERSION} COMPONENTS Development)
27+
set(PYTHON_SUFFIX "${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}")
28+
find_package(Boost 1.63 COMPONENTS "numpy${PYTHON_SUFFIX}" "python${PYTHON_SUFFIX}")
29+
30+
if (Boost_FOUND)
31+
#===============================================================================
32+
# Declare the library dependencies here
33+
# Example:
34+
# elements_add_library(ElementsExamples src/Lib/*.cpp
35+
# INCLUDE_DIRS Boost ElementsKernel
36+
# LINK_LIBRARIES Boost ElementsKernel
37+
# PUBLIC_HEADERS ElementsExamples)
38+
#===============================================================================
39+
elements_add_python_module(SEPythonModule
40+
src/lib/*.cpp
41+
LINK_LIBRARIES SEImplementation SEMain Boost PythonInterp
42+
)
43+
44+
#===============================================================================
45+
# Declare the executables here
46+
# Example:
47+
# elements_add_executable(ElementsProgramExample src/Program/ProgramExample.cpp
48+
# INCLUDE_DIRS Boost ElementsExamples
49+
# LINK_LIBRARIES Boost ElementsExamples)
50+
#===============================================================================
51+
52+
#===============================================================================
53+
# Declare the Boost tests here
54+
# Example:
55+
# elements_add_unit_test(BoostClassExample tests/src/Boost/ClassExample_test.cpp
56+
# EXECUTABLE BoostClassExample_test
57+
# INCLUDE_DIRS ElementsExamples
58+
# LINK_LIBRARIES ElementsExamples TYPE Boost)
59+
#===============================================================================
60+
61+
#===============================================================================
62+
# Use the following macro for python modules, scripts and aux files:
63+
# elements_install_python_modules()
64+
# elements_install_scripts()
65+
#===============================================================================
66+
67+
#===============================================================================
68+
# Declare the Python programs here
69+
# Examples :
70+
# elements_add_python_program(PythonProgramExample
71+
# ElementsExamples.PythonProgramExample)
72+
#===============================================================================
73+
74+
#===============================================================================
75+
# Add the elements_install_conf_files macro
76+
# Examples:
77+
# elements_install_conf_files()
78+
#===============================================================================
79+
endif (Boost_FOUND)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* Copyright © 2022 Université de Genève, LMU Munich - Faculty of Physics, IAP-CNRS/Sorbonne Université
3+
*
4+
* This library is free software; you can redistribute it and/or modify it under
5+
* the terms of the GNU Lesser General Public License as published by the Free
6+
* Software Foundation; either version 3.0 of the License, or (at your option)
7+
* any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11+
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12+
* details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public License
15+
* along with this library; if not, write to the Free Software Foundation, Inc.,
16+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17+
*/
18+
19+
#ifndef SOURCEXTRACTORPLUSPLUS_CONFIGADAPTER_H
20+
#define SOURCEXTRACTORPLUSPLUS_CONFIGADAPTER_H
21+
22+
#include <boost/program_options/options_description.hpp>
23+
#include <boost/program_options/variables_map.hpp>
24+
#include <boost/python/dict.hpp>
25+
#include <map>
26+
27+
namespace SourceXPy {
28+
29+
class ConfigAdapter {
30+
public:
31+
using config_map_t = std::map<std::string, boost::program_options::variable_value>;
32+
33+
explicit ConfigAdapter(boost::program_options::options_description opt_desc);
34+
35+
void fromPython(const boost::python::dict& config);
36+
37+
template <typename T>
38+
void set(const std::string& key, T&& value) {
39+
m_options[key] = boost::program_options::variable_value(std::forward<T>(value), false);
40+
}
41+
42+
const config_map_t& getOptions() const;
43+
44+
private:
45+
boost::program_options::options_description m_option_descriptions;
46+
config_map_t m_options;
47+
};
48+
49+
} // namespace SourceXPy
50+
51+
#endif // SOURCEXTRACTORPLUSPLUS_CONFIGADAPTER_H

0 commit comments

Comments
 (0)