Skip to content

Commit 6795c53

Browse files
committed
Added generic python __call__ method for process objects.
Bumped version to 4.17.2
1 parent a21455e commit 6795c53

3 files changed

Lines changed: 92 additions & 5 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ project(FAST)
77

88
set(VERSION_MAJOR 4)
99
set(VERSION_MINOR 17)
10-
set(VERSION_PATCH 1)
10+
set(VERSION_PATCH 2)
1111
set(VERSION_SO 4) # SO version, should be incremented by 1 every time the existing API changes
1212
set(FAST_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
1313

source/FAST/Python/Core.i.in

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -649,10 +649,55 @@ static float* _intToFloatPointer(std::size_t intPointer) {
649649

650650
%extend fast::ProcessObject {
651651
%pythoncode %{
652-
def getDataStream(self):
653-
return DataStream(self)
652+
def getDataStream(self):
653+
return DataStream(self)
654+
655+
def __call__(self, *args: Tuple[Union[DataObject, 'ProcessObject', Tuple[Union[DataObject, 'ProcessObject', int], ...]], ...]) -> Union[DataObject, List[DataObject]]:
656+
"""
657+
Connect input data to this process object, run, and return all output data.
658+
Input data must be a list of data or process objects. Input and output ports can be provided using a tuple.
659+
For example
660+
PO = SomeProcessObject()
661+
output = PO(inputData1, inputPO2) # Only provide data sources, input ports are assumed to be 0, 1, ...
662+
output = PO((inputPO, 1), (inputPO, 0)) # Specify output ports to connect
663+
output = PO((1, inputPO, 1), (0, inputPO, 0)) # Specify both output ports and input ports
664+
output = PO((1, inputPO), (0, inputPO)) # Specify input ports
665+
"""
666+
for index, arg in enumerate(args):
667+
if isinstance(arg, tuple):
668+
if len(arg) == 2:
669+
if isinstance(arg[0], int):
670+
inputPort = arg[0]
671+
source = arg[1]
672+
outputPort = 0
673+
else:
674+
inputPort = 0
675+
source = arg[0]
676+
outputPort = arg[1]
677+
elif len(arg) == 3:
678+
inputPort, source, outputPort = arg
679+
else:
680+
raise ValueError('Input data tuple given to __call__() must have 2 or 3 items.')
681+
else:
682+
inputPort = index
683+
outputPort = 0
684+
source = arg
685+
# Type check
686+
if isinstance(source, ProcessObject):
687+
self.connect(inputPort, source, outputPort)
688+
elif isinstance(source, DataObject):
689+
self.connect(inputPort, source)
690+
else:
691+
raise ValueError('Data source given to __call__() must be a ProcessObject or a DataObject')
692+
self.run()
693+
outputData = []
694+
for i in range(self.getNrOfOutputPorts()):
695+
outputData.append(self.getOutput(i))
696+
if len(outputData) == 1:
697+
return outputData[0]
698+
else:
699+
return outputData
654700
%}
655-
656701
}
657702

658703
/*
@@ -667,4 +712,4 @@ static float* _intToFloatPointer(std::size_t intPointer) {
667712
}
668713
*/
669714

670-
%include "ProcessObjects.i"
715+
%include "ProcessObjects.i"
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import fast
2+
import pytest
3+
4+
5+
def test_callable_process_object():
6+
image = fast.Image.create(512, 512, fast.TYPE_UINT8, 1)
7+
image2 = fast.ImageResizer.create(256, 256)(image)
8+
assert image2.getWidth() == 256
9+
assert image2.getHeight() == 256
10+
11+
image2 = fast.ImageResizer.create(256, 256)((0, image))
12+
assert image2.getWidth() == 256
13+
assert image2.getHeight() == 256
14+
15+
resize = fast.ImageResizer.create(256, 256).connect(image)
16+
image2 = fast.GrayscaleToColor.create()(resize)
17+
assert image2.getWidth() == 256
18+
assert image2.getHeight() == 256
19+
assert image2.getNrOfChannels() == 3
20+
21+
image2 = fast.GrayscaleToColor.create()((0, resize, 0))
22+
assert image2.getWidth() == 256
23+
assert image2.getHeight() == 256
24+
assert image2.getNrOfChannels() == 3
25+
26+
27+
def test_callable_process_object_exceptions():
28+
with pytest.raises(ValueError):
29+
image2 = fast.ImageResizer.create(256, 256)(32)
30+
with pytest.raises(RuntimeError):
31+
image2 = fast.ImageResizer.create(256, 256)()
32+
image = fast.Image.create(512, 512, fast.TYPE_UINT8, 1)
33+
with pytest.raises(RuntimeError):
34+
image2 = fast.ImageResizer.create(256, 256)(image, image)
35+
with pytest.raises(RuntimeError):
36+
image2 = fast.ImageResizer.create(256, 256)((1, image))
37+
38+
resize = fast.ImageResizer.create(256, 256).connect(image)
39+
with pytest.raises(RuntimeError):
40+
image2 = fast.GrayscaleToColor.create()((0, resize, 3))
41+
with pytest.raises(ValueError):
42+
image2 = fast.GrayscaleToColor.create()((0, resize, 3, 2))

0 commit comments

Comments
 (0)