Skip to content

Commit 6c8e15a

Browse files
committed
Documenting and some last touches
1 parent 2a45f3f commit 6c8e15a

File tree

12 files changed

+329
-16
lines changed

12 files changed

+329
-16
lines changed

SEPythonModule/SEPythonModule/ConfigAdapter.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,29 @@
2626

2727
namespace SourceXPy {
2828

29+
/**
30+
* @brief Wraps boost's program options so they can be populated from a Python dictionary
31+
*/
2932
class ConfigAdapter {
3033
public:
3134
using config_map_t = std::map<std::string, boost::program_options::variable_value>;
3235

36+
/**
37+
* Constructor. Initialize the option values with the default values.
38+
* @param opt_desc Set of program expected options
39+
* @see Euclid::Configuration::ConfigManager::closeRegistration
40+
*/
3341
explicit ConfigAdapter(boost::program_options::options_description opt_desc);
3442

43+
/**
44+
* Set / override defaults with the values from a Python dictionary
45+
* @param config
46+
*/
3547
void fromPython(const boost::python::dict& config);
3648

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-
49+
/**
50+
* @return The initialized option map
51+
*/
4252
const config_map_t& getOptions() const;
4353

4454
private:

SEPythonModule/SEPythonModule/Context.h

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,36 @@ class SourceInterface;
4949
namespace SourceXPy {
5050

5151
/**
52-
* Wrap the required context for a sourcextractor++ run
52+
* @brief Wrap the required context for a sourcextractor++ run
53+
* @details
54+
* A context includes factory methods, configuration manager, etc.
5355
*/
5456
class Context {
5557
public:
58+
/**
59+
* Constructor
60+
* @param global_config
61+
* Global configuration (i.e., detection, background), equivalent to the content from a `.conf` file
62+
* @param measurement_config
63+
* Measurement configuration (an instance of sourcextractor.config.measurement_config.MeasurementConfig)
64+
* If None, `global_measurement_config` will be used as usual, but this prevents multiple contexts
65+
* from being useful.
66+
*/
5667
Context(const boost::python::dict& global_config, const boost::python::object& measurement_config);
68+
69+
/**
70+
* Non copyable
71+
*/
5772
Context(const Context&) = delete;
58-
Context(Context&&) = default;
5973

74+
/**
75+
* Movable
76+
*/
77+
Context(Context&&) = default;
78+
79+
/**
80+
* @return A dictionary where they key is the property name, and the value a list of output columns / attributes
81+
*/
6082
boost::python::dict get_properties() const;
6183

6284
std::shared_ptr<Euclid::Configuration::ConfigManager> m_config_manager;
@@ -74,21 +96,49 @@ class Context {
7496
std::shared_ptr<SourceXtractor::OutputFactory> m_output_factory;
7597
std::function<Euclid::Table::Row(const SourceXtractor::SourceInterface&)> m_source_to_row;
7698

77-
static void enter(const std::shared_ptr<Context>&);
78-
static void exit(const std::shared_ptr<Context>&, const boost::python::object& exc_type,
79-
const boost::python::object& exc_value, const boost::python::object& traceback);
99+
/**
100+
* Set `context` as the default context when instantiating pipeline stages.
101+
* @see https://docs.python.org/3/reference/datamodel.html#object.__enter__
102+
*/
103+
static void enter(const std::shared_ptr<Context>& context);
104+
105+
/**
106+
* Clear the default context
107+
* @see https://docs.python.org/3/reference/datamodel.html#object.__exit__
108+
*/
109+
static void exit(const std::shared_ptr<Context>& context, const boost::python::object& exc_type,
110+
const boost::python::object& exc_value, const boost::python::object& traceback);
111+
112+
/**
113+
* @return The active default context
114+
*/
80115
static const std::shared_ptr<Context>& get_global_context();
81116

82117
private:
118+
/**
119+
* One default context per thread
120+
*/
83121
static thread_local std::shared_ptr<Context> s_context;
84122
};
85123

124+
/**
125+
* Helper class that uses the thread default context when we get a None from Python
126+
*/
86127
class ContextPtr {
87128
public:
129+
/**
130+
* Constructor
131+
* @param ptr The Context to use. If None (nullptr), use the thread default.
132+
* @throw boost::python::error_already_set if both the parameter and the default context are null
133+
*/
88134
ContextPtr(std::shared_ptr<Context> ptr) : m_ptr(std::move(ptr)) { // NOLINT: Allow implicit conversion
89135
if (!m_ptr) {
90136
m_ptr = Context::get_global_context();
91137
}
138+
if (!m_ptr) {
139+
PyErr_SetString(PyExc_ValueError, "Missing Context");
140+
boost::python::throw_error_already_set();
141+
}
92142
}
93143

94144
Context* operator->() const {

SEPythonModule/SEPythonModule/Deblending.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,46 @@
2525

2626
namespace SourceXPy {
2727

28+
/**
29+
* Wrap the Deblending stage
30+
*/
2831
class Deblending : public SourceXtractor::PipelineReceiver<SourceXtractor::SourceGroupInterface> {
2932
public:
33+
/**
34+
* Constructor
35+
* @param context
36+
*/
3037
explicit Deblending(ContextPtr context);
38+
3139
~Deblending() override = default;
3240

41+
/**
42+
* @return String representation of a Deblending instance
43+
*/
3344
std::string repr() const;
3445

46+
/**
47+
* Set the next stage
48+
* @param callback A Python callable object that should be able to receive *groups* and *events*
49+
*/
3550
void setNextStage(const boost::python::object& callback);
3651

37-
void receiveSource(std::unique_ptr<SourceXtractor::SourceGroupInterface> source) override;
52+
/**
53+
* To be called (from sourcextractor++) when there is a group ready to deblend
54+
*/
55+
void receiveSource(std::unique_ptr<SourceXtractor::SourceGroupInterface> group) override;
3856

57+
/**
58+
* To be called (from sourcextractor++) when there is a process event
59+
*/
3960
void receiveProcessSignal(const SourceXtractor::ProcessSourcesEvent& event) override;
4061

62+
/**
63+
* To be called (from Python) when there is either a group or an event ready
64+
* @param obj A Python object, which should be either a SourceXPy::SourceGroup or a SourceXPy::ProcessSourcesEvent
65+
* @throw boost::python_error_already_set If obj is neither of those
66+
* @details obj may be cloned, since we can not know if Python is / will be keeping a reference to obj
67+
*/
4168
void call(const boost::python::object& obj) const;
4269

4370
private:

SEPythonModule/SEPythonModule/FitsOutput.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,47 @@ class Output;
3030

3131
namespace SourceXPy {
3232

33+
/**
34+
* Wrap the Output stage. This is the last stage on a Pipeline.
35+
* @details It expects a SourceXPy::AllFramesDone process event signaling the end of the processing.
36+
*/
3337
class FitsOutput : public SourceXtractor::PipelineReceiver<SourceXtractor::SourceGroupInterface> {
3438
public:
39+
/**
40+
* Constructor
41+
* @param context
42+
*/
3543
explicit FitsOutput(ContextPtr context);
44+
3645
~FitsOutput() override;
3746

47+
/**
48+
* @return String representation of a FitsOutput instance
49+
*/
3850
std::string repr() const;
3951

52+
/**
53+
* To be called (from sourcextractor++) when there is a group ready to deblend
54+
*/
4055
void receiveSource(std::unique_ptr<SourceXtractor::SourceGroupInterface> group) override;
4156

57+
/**
58+
* To be called (from sourcextractor++) when there is a process event
59+
*/
4260
void receiveProcessSignal(const SourceXtractor::ProcessSourcesEvent& event) override;
4361

62+
/**
63+
* To be called (from Python) when there is either a group or an event ready
64+
* @param obj A Python object, which should be either a SourceXPy::SourceGroup or a SourceXPy::ProcessSourcesEvent
65+
* @throw boost::python_error_already_set If obj is neither of those
66+
* @details obj may be cloned, since we can not know if Python is / will be keeping a reference to obj
67+
*/
4468
void call(const boost::python::object& obj);
4569

70+
/**
71+
* Wait until the processing is done, return nothing.
72+
* @todo Maybe add a timeout and return a boolean if ready?
73+
*/
4674
void get();
4775

4876
private:

SEPythonModule/SEPythonModule/Grouping.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,46 @@
2424

2525
namespace SourceXPy {
2626

27+
/**
28+
* Wrap the Grouping stage
29+
*/
2730
class Grouping : public SourceXtractor::PipelineReceiver<SourceXtractor::SourceInterface> {
2831
public:
32+
/**
33+
* Constructor
34+
* @param context
35+
*/
2936
explicit Grouping(ContextPtr context);
37+
3038
~Grouping() override = default;
3139

40+
/**
41+
* @return String representation of a Deblending instance
42+
*/
3243
std::string repr() const;
3344

45+
/**
46+
* Set the next stage
47+
* @param callback A Python callable object that should be able to receive *groups* and *events*
48+
*/
3449
void setNextStage(const boost::python::object& callback);
3550

51+
/**
52+
* To be called (from sourcextractor++) when there is a group ready to deblend
53+
*/
3654
void receiveSource(std::unique_ptr<SourceXtractor::SourceInterface> source) override;
3755

56+
/**
57+
* To be called (from sourcextractor++) when there is a process event
58+
*/
3859
void receiveProcessSignal(const SourceXtractor::ProcessSourcesEvent& event) override;
3960

61+
/**
62+
* To be called (from Python) when there is either a group or an event ready
63+
* @param obj A Python object, which should be either a SourceXPy::SourceGroup or a SourceXPy::ProcessSourcesEvent
64+
* @throw boost::python_error_already_set If obj is neither of those
65+
* @details obj may be cloned, since we can not know if Python is / will be keeping a reference to obj
66+
*/
4067
void call(const boost::python::object& obj) const;
4168

4269
private:

SEPythonModule/SEPythonModule/Measurement.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,47 @@
2626

2727
namespace SourceXPy {
2828

29+
/**
30+
* Wrap the Measurement stage.
31+
* Not strictly required, but implements the Multithreading measurement.
32+
*/
2933
class Measurement : public SourceXtractor::PipelineReceiver<SourceXtractor::SourceGroupInterface> {
3034
public:
35+
/**
36+
* Constructor
37+
* @param context
38+
*/
3139
explicit Measurement(ContextPtr context);
40+
3241
~Measurement() override;
3342

43+
/**
44+
* @return String representation of a Measurement instance
45+
*/
3446
std::string repr() const;
3547

48+
/**
49+
* Set the next stage
50+
* @param callback A Python callable object that should be able to receive *groups* and *events*
51+
*/
3652
void setNextStage(const boost::python::object& callback);
3753

54+
/**
55+
* To be called (from sourcextractor++) when there is a group ready to deblend
56+
*/
3857
void receiveSource(std::unique_ptr<SourceXtractor::SourceGroupInterface> group) override;
3958

59+
/**
60+
* To be called (from sourcextractor++) when there is a process event
61+
*/
4062
void receiveProcessSignal(const SourceXtractor::ProcessSourcesEvent& event) override;
4163

64+
/**
65+
* To be called (from Python) when there is either a group or an event ready
66+
* @param obj A Python object, which should be either a SourceXPy::SourceGroup or a SourceXPy::ProcessSourcesEvent
67+
* @throw boost::python_error_already_set If obj is neither of those
68+
* @details obj may be cloned, since we can not know if Python is / will be keeping a reference to obj
69+
*/
4270
void call(const boost::python::object& obj);
4371

4472
private:

SEPythonModule/SEPythonModule/NumpyOutput.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,48 @@
2727

2828
namespace SourceXPy {
2929

30+
/**
31+
* Python specific output stage. It converts the Table output to a Numpy array.
32+
* @details It expects a SourceXPy::AllFramesDone process event signaling the end of the processing.
33+
*/
3034
class NumpyOutput : public SourceXtractor::PipelineReceiver<SourceXtractor::SourceGroupInterface> {
3135
public:
36+
/**
37+
* Constructor
38+
* @param context
39+
*/
3240
explicit NumpyOutput(ContextPtr context);
41+
3342
~NumpyOutput() override;
3443

44+
/**
45+
* @return String representation of a NumpyOutput instance
46+
*/
3547
std::string repr() const;
3648

49+
/**
50+
* To be called (from sourcextractor++) when there is a group ready to deblend
51+
*/
3752
void receiveSource(std::unique_ptr<SourceXtractor::SourceGroupInterface> group) override;
3853

54+
/**
55+
* To be called (from sourcextractor++) when there is a process event
56+
*/
3957
void receiveProcessSignal(const SourceXtractor::ProcessSourcesEvent& event) override;
4058

59+
/**
60+
* To be called (from Python) when there is either a group or an event ready
61+
* @param obj A Python object, which should be either a SourceXPy::SourceGroup or a SourceXPy::ProcessSourcesEvent
62+
* @throw boost::python_error_already_set If obj is neither of those
63+
* @details obj may be cloned, since we can not know if Python is / will be keeping a reference to obj
64+
*/
4165
void call(const boost::python::object& obj);
4266

67+
/**
68+
* Wait until the processing is done.
69+
* @return A numpy structured array with the generated output.
70+
* @todo Maybe add a timeout and return a None when not ready?
71+
*/
4372
boost::python::object getTable();
4473

4574
private:

0 commit comments

Comments
 (0)