Skip to content

Commit 7084fb5

Browse files
committed
Closes #1298, closes #1282
1 parent a7beaa1 commit 7084fb5

File tree

4 files changed

+244
-44
lines changed

4 files changed

+244
-44
lines changed
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
2+
<!DOCTYPE boost_serialization>
3+
<boost_serialization signature="serialization::archive" version="12">
4+
<networkFile class_id="0" tracking_level="0" version="3">
5+
<networkInfo class_id="1" tracking_level="0" version="0">
6+
<modules class_id="2" tracking_level="0" version="0">
7+
<count>3</count>
8+
<item_version>0</item_version>
9+
<item class_id="3" tracking_level="0" version="0">
10+
<first>CreateString:0</first>
11+
<second class_id="4" tracking_level="0" version="0">
12+
<module class_id="5" tracking_level="0" version="0">
13+
<package_name_>SCIRun</package_name_>
14+
<category_name_>String</category_name_>
15+
<module_name_>CreateString</module_name_>
16+
</module>
17+
<state class_id="6" tracking_level="0" version="0">
18+
<stateMap class_id="7" tracking_level="0" version="0">
19+
<count>1</count>
20+
<item_version>0</item_version>
21+
<item class_id="8" tracking_level="0" version="0">
22+
<first class_id="9" tracking_level="0" version="0">
23+
<name>InputString</name>
24+
</first>
25+
<second class_id="10" tracking_level="0" version="0">
26+
<name>InputString</name>
27+
<value class_id="11" tracking_level="0" version="0">
28+
<which>2</which>
29+
<value>hello</value>
30+
</value>
31+
</second>
32+
</item>
33+
</stateMap>
34+
</state>
35+
</second>
36+
</item>
37+
<item>
38+
<first>InterfaceWithPython:0</first>
39+
<second>
40+
<module>
41+
<package_name_>SCIRun</package_name_>
42+
<category_name_>Python</category_name_>
43+
<module_name_>InterfaceWithPython</module_name_>
44+
</module>
45+
<state>
46+
<stateMap>
47+
<count>1</count>
48+
<item_version>0</item_version>
49+
<item>
50+
<first>
51+
<name>PythonCode</name>
52+
</first>
53+
<second>
54+
<name>PythonCode</name>
55+
<value>
56+
<which>2</which>
57+
<value>s = scirun_get_module_input_value_by_index(&quot;InterfaceWithPython:0&quot;, 2)
58+
s2 = s + &quot; from python!&quot;
59+
scirun_set_module_transient_state(&quot;InterfaceWithPython:0&quot;, &quot;PythonObject&quot;, s2)</value>
60+
</value>
61+
</second>
62+
</item>
63+
</stateMap>
64+
</state>
65+
</second>
66+
</item>
67+
<item>
68+
<first>ReportStringInfo:0</first>
69+
<second>
70+
<module>
71+
<package_name_>SCIRun</package_name_>
72+
<category_name_>String</category_name_>
73+
<module_name_>ReportStringInfo</module_name_>
74+
</module>
75+
<state>
76+
<stateMap>
77+
<count>0</count>
78+
<item_version>0</item_version>
79+
</stateMap>
80+
</state>
81+
</second>
82+
</item>
83+
</modules>
84+
<connections class_id="12" tracking_level="0" version="0">
85+
<count>2</count>
86+
<item_version>0</item_version>
87+
<item class_id="13" tracking_level="0" version="0">
88+
<moduleId1_>CreateString:0</moduleId1_>
89+
<port1_ class_id="14" tracking_level="0" version="0">
90+
<name>NewString</name>
91+
<id>0</id>
92+
</port1_>
93+
<moduleId2_>InterfaceWithPython:0</moduleId2_>
94+
<port2_>
95+
<name>InputString</name>
96+
<id>0</id>
97+
</port2_>
98+
</item>
99+
<item>
100+
<moduleId1_>InterfaceWithPython:0</moduleId1_>
101+
<port1_>
102+
<name>PythonString</name>
103+
<id>0</id>
104+
</port1_>
105+
<moduleId2_>ReportStringInfo:0</moduleId2_>
106+
<port2_>
107+
<name>Input</name>
108+
<id>0</id>
109+
</port2_>
110+
</item>
111+
</connections>
112+
</networkInfo>
113+
<modulePositions class_id="15" tracking_level="0" version="0">
114+
<count>3</count>
115+
<item_version>0</item_version>
116+
<item class_id="16" tracking_level="0" version="0">
117+
<first>CreateString:0</first>
118+
<second class_id="17" tracking_level="0" version="0">
119+
<first>-1.62000000000000000e+002</first>
120+
<second>-4.80000000000000000e+002</second>
121+
</second>
122+
</item>
123+
<item>
124+
<first>InterfaceWithPython:0</first>
125+
<second>
126+
<first>-2.43000000000000000e+002</first>
127+
<second>-3.57000000000000000e+002</second>
128+
</second>
129+
</item>
130+
<item>
131+
<first>ReportStringInfo:0</first>
132+
<second>
133+
<first>-2.45000000000000000e+002</first>
134+
<second>-1.76000000000000000e+002</second>
135+
</second>
136+
</item>
137+
</modulePositions>
138+
<moduleNotes class_id="18" tracking_level="0" version="0">
139+
<count>0</count>
140+
<item_version>0</item_version>
141+
</moduleNotes>
142+
<connectionNotes>
143+
<count>0</count>
144+
<item_version>0</item_version>
145+
</connectionNotes>
146+
<moduleTags class_id="19" tracking_level="0" version="0">
147+
<count>3</count>
148+
<item_version>0</item_version>
149+
<item class_id="20" tracking_level="0" version="0">
150+
<first>CreateString:0</first>
151+
<second>0</second>
152+
</item>
153+
<item>
154+
<first>InterfaceWithPython:0</first>
155+
<second>0</second>
156+
</item>
157+
<item>
158+
<first>ReportStringInfo:0</first>
159+
<second>0</second>
160+
</item>
161+
</moduleTags>
162+
</networkFile>
163+
</boost_serialization>
164+

src/Modules/Python/InterfaceWithPython.cc

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@
2727
*/
2828

2929
#include <Modules/Python/InterfaceWithPython.h>
30+
#include <Modules/Python/PythonObjectForwarder.h>
3031
#include <Core/Datatypes/String.h>
3132
#include <Core/Datatypes/DenseMatrix.h>
3233
#include <Core/Python/PythonInterpreter.h>
3334
#include <boost/thread.hpp>
35+
#include <boost/algorithm/string.hpp>
3436

3537
using namespace SCIRun::Modules::Python;
3638
using namespace SCIRun::Core::Datatypes;
@@ -65,8 +67,19 @@ void InterfaceWithPython::setStateDefaults()
6567

6668
void InterfaceWithPython::execute()
6769
{
68-
Guard g(lock_.get());
6970
auto state = get_state();
70-
auto code = state->getValue(Parameters::PythonCode).toString();
71-
PythonInterpreter::Instance().run_string(code);
71+
{
72+
Guard g(lock_.get());
73+
74+
auto code = state->getValue(Parameters::PythonCode).toString();
75+
std::vector<std::string> lines;
76+
boost::split(lines, code, boost::is_any_of("\n"));
77+
for (const auto& line : lines)
78+
PythonInterpreter::Instance().run_string(line);
79+
}
80+
81+
//TODO: hook up GUI input as with POF module
82+
//TODO: support multiple output objects
83+
PythonObjectForwarderImpl<InterfaceWithPython> impl(*this, 100, 100);
84+
impl.waitForOutputFromTransientState();
7285
}

src/Modules/Python/PythonObjectForwarder.cc

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@
2727
*/
2828

2929
#include <Modules/Python/PythonObjectForwarder.h>
30-
#include <Core/Datatypes/String.h>
31-
#include <Core/Datatypes/DenseMatrix.h>
32-
#include <boost/thread.hpp>
30+
3331

3432
using namespace SCIRun::Modules::Python;
3533
using namespace SCIRun::Core::Datatypes;
@@ -60,45 +58,10 @@ void PythonObjectForwarder::setStateDefaults()
6058
void PythonObjectForwarder::execute()
6159
{
6260
auto state = get_state();
63-
int tries = 0;
6461
const int maxTries = state->getValue(Parameters::NumberOfRetries).toInt();
6562
const int waitTime = state->getValue(Parameters::PollingIntervalMilliseconds).toInt();
66-
auto valueOption = state->getTransientValue(Parameters::PythonObject);
67-
68-
while (tries < maxTries && !valueOption)
69-
{
70-
std::ostringstream ostr;
71-
ostr << "PythonObjectForwarder looking up value attempt #" << (tries+1) << "/" << maxTries;
72-
remark(ostr.str());
73-
74-
valueOption = state->getTransientValue(Parameters::PythonObject);
7563

76-
tries++;
77-
boost::this_thread::sleep(boost::posix_time::milliseconds(waitTime));
78-
}
79-
80-
if (valueOption)
81-
{
82-
auto var = transient_value_cast<Variable>(valueOption);
83-
if (var.name().name() == "string")
84-
{
85-
auto valueStr = var.toString();
86-
if (!valueStr.empty())
87-
sendOutput(PythonString, boost::make_shared<String>(valueStr));
88-
else
89-
sendOutput(PythonString, boost::make_shared<String>("Empty string or non-string received"));
90-
}
91-
else if (var.name().name() == "dense matrix")
92-
{
93-
auto dense = boost::dynamic_pointer_cast<DenseMatrix>(var.getDatatype());
94-
if (dense)
95-
sendOutput(PythonMatrix, dense);
96-
}
97-
else if (var.name().name() == "sparse matrix")
98-
{
99-
auto sparse = boost::dynamic_pointer_cast<SparseRowMatrix>(var.getDatatype());
100-
if (sparse)
101-
sendOutput(PythonMatrix, sparse);
102-
}
103-
}
64+
PythonObjectForwarderImpl<PythonObjectForwarder> impl(*this, maxTries, waitTime);
65+
impl.waitForOutputFromTransientState();
10466
}
67+

src/Modules/Python/PythonObjectForwarder.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
#define MODULES_PYTHON_PYTHONOBJECTFORWARDER_H
3131

3232
#include <Dataflow/Network/Module.h>
33+
#include <Core/Datatypes/String.h>
34+
#include <Core/Datatypes/DenseMatrix.h>
35+
#include <Core/Datatypes/SparseRowMatrix.h>
36+
#include <boost/thread.hpp>
3337
#include <Modules/Python/share.h>
3438

3539
namespace SCIRun
@@ -43,6 +47,62 @@ namespace SCIRun
4347
ALGORITHM_PARAMETER_DECL(PollingIntervalMilliseconds);
4448
ALGORITHM_PARAMETER_DECL(NumberOfRetries);
4549
ALGORITHM_PARAMETER_DECL(PythonObject);
50+
51+
52+
template <class PythonModule>
53+
class PythonObjectForwarderImpl
54+
{
55+
public:
56+
PythonObjectForwarderImpl(PythonModule& module, int maxTries, int waitTime) : module_(module), maxTries_(maxTries), waitTime_(waitTime) {}
57+
58+
void waitForOutputFromTransientState()
59+
{
60+
int tries = 0;
61+
auto state = module_.get_state();
62+
auto valueOption = state->getTransientValue(Parameters::PythonObject);
63+
64+
while (tries < maxTries_ && !valueOption)
65+
{
66+
std::ostringstream ostr;
67+
ostr << "PythonObjectForwarder looking up value attempt #" << (tries + 1) << "/" << maxTries_;
68+
module_.remark(ostr.str());
69+
70+
valueOption = state->getTransientValue(Parameters::PythonObject);
71+
72+
tries++;
73+
boost::this_thread::sleep(boost::posix_time::milliseconds(waitTime_));
74+
}
75+
76+
if (valueOption)
77+
{
78+
auto var = transient_value_cast<Variable>(valueOption);
79+
if (var.name().name() == "string")
80+
{
81+
auto valueStr = var.toString();
82+
if (!valueStr.empty())
83+
module_.sendOutput(module_.PythonString, boost::make_shared<Core::Datatypes::String>(valueStr));
84+
else
85+
module_.sendOutput(module_.PythonString, boost::make_shared<Core::Datatypes::String>("Empty string or non-string received"));
86+
}
87+
else if (var.name().name() == "dense matrix")
88+
{
89+
auto dense = boost::dynamic_pointer_cast<Core::Datatypes::DenseMatrix>(var.getDatatype());
90+
if (dense)
91+
module_.sendOutput(module_.PythonMatrix, dense);
92+
}
93+
else if (var.name().name() == "sparse matrix")
94+
{
95+
auto sparse = boost::dynamic_pointer_cast<Core::Datatypes::SparseRowMatrix>(var.getDatatype());
96+
if (sparse)
97+
module_.sendOutput(module_.PythonMatrix, sparse);
98+
}
99+
}
100+
101+
}
102+
private:
103+
PythonModule& module_;
104+
int maxTries_, waitTime_;
105+
};
46106
}
47107
}
48108
}

0 commit comments

Comments
 (0)