Skip to content

Commit 5b151e1

Browse files
Fix argument order for subtract and divide between different container types (#2133)
When doing an operation the __container_priority__ is compared with other. If other has a higher priority, then the operator is called from other with self as the argument. This is fine for commutative operations, but not for sub and divide. --------- Signed-off-by: Margaret Duff <[email protected]> Co-authored-by: Edoardo Pasca <[email protected]>
1 parent cb030eb commit 5b151e1

File tree

3 files changed

+39
-4
lines changed

3 files changed

+39
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- Ensured the same approximate gradient is used within each iteration for PD3O with a stochastic function `f` (#2043)
88
- Fix `recon.FBP` `split_processing` methods for `ASTRA` backend (#2114)
99
- Copy geometry in the creation of a DataContainer (#2108)
10+
- Fix order of operations for subtraction and division between a BlockDataContainer and DataContainer (#2133)
1011
- Documentation:
1112
- Updated documentation for the ChannelWiseOperator including new example (#2096)
1213
- Updated documentation for LADMM (#2015)

Wrappers/Python/cil/framework/data_container.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ def add(self, other, *args, **kwargs):
466466
def subtract(self, other, *args, **kwargs):
467467
if hasattr(other, '__container_priority__') and \
468468
self.__class__.__container_priority__ < other.__class__.__container_priority__:
469-
return other.subtract(self, *args, **kwargs)
469+
return other.sapyb(-1,self,1, out=kwargs.get('out', None))
470470
return self.pixel_wise_binary(numpy.subtract, other, *args, **kwargs)
471471

472472
def multiply(self, other, *args, **kwargs):
@@ -478,7 +478,9 @@ def multiply(self, other, *args, **kwargs):
478478
def divide(self, other, *args, **kwargs):
479479
if hasattr(other, '__container_priority__') and \
480480
self.__class__.__container_priority__ < other.__class__.__container_priority__:
481-
return other.divide(self, *args, **kwargs)
481+
_out = other.divide(self, *args, **kwargs)
482+
_out.power(-1, out=_out)
483+
return _out
482484
return self.pixel_wise_binary(numpy.divide, other, *args, **kwargs)
483485

484486
def power(self, other, *args, **kwargs):

Wrappers/Python/test/test_BlockDataContainer.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import unittest
2020
from utils import initialise_tests
2121
import numpy as np
22-
from cil.framework import ImageGeometry, AcquisitionGeometry, VectorGeometry, ImageData, Partitioner, AcquisitionData
22+
from cil.framework import ImageGeometry, AcquisitionGeometry, VectorGeometry, ImageData, Partitioner, AcquisitionData, DataContainer
2323
from cil.framework import BlockDataContainer, BlockGeometry
2424
import functools
2525

@@ -643,7 +643,39 @@ def test_sapyb_ab_blockdc_y_dc(self):
643643
out = cp0.sapyb(a,data1,b, num_threads=4)
644644

645645
self.assertBlockDataContainerEqual(out, res)
646-
646+
647+
def test_BlockDataContainer_mixed_arithmetic(self):
648+
a = numpy.ones([2, 2], dtype=numpy.float32) * 2
649+
b = numpy.ones([2, 2], dtype=numpy.float32) * 4
650+
c = numpy.ones([2, 2], dtype=numpy.float32) * 3
651+
652+
bdc = BlockDataContainer(DataContainer(a))
653+
bdc2 = BlockDataContainer(DataContainer(a), DataContainer(b))
654+
dc = DataContainer(b)
655+
dc2 = DataContainer(c)
656+
657+
sub1 = bdc - dc # 2 - 4
658+
self.assertIsInstance(sub1, BlockDataContainer)
659+
np.testing.assert_almost_equal(sub1.get_item(0).as_array(), -2, decimal=5)
660+
661+
sub2 = dc - bdc # 4 - 2
662+
self.assertIsInstance(sub2, BlockDataContainer)
663+
np.testing.assert_almost_equal(sub2.get_item(0).as_array(), 2, decimal=5)
664+
665+
sub3 = dc2 - bdc2 # 3 - (2, 4)
666+
self.assertIsInstance(sub3, BlockDataContainer)
667+
np.testing.assert_almost_equal(sub3.get_item(0).as_array(), 1, decimal=5)
668+
np.testing.assert_almost_equal(sub3.get_item(1).as_array(), -1, decimal=5)
669+
670+
div1 = bdc / dc # 2 / 4
671+
self.assertIsInstance(div1, BlockDataContainer)
672+
np.testing.assert_almost_equal(div1.get_item(0).as_array(), 0.5, decimal=5)
673+
674+
div2 = dc / bdc # 4 / 2
675+
self.assertIsInstance(div2, BlockDataContainer)
676+
np.testing.assert_almost_equal(div2.get_item(0).as_array(), 2, decimal=5)
677+
678+
647679
class TestOutParameter(BDCUnittest):
648680
def setUp(self):
649681
ig0 = ImageGeometry(2,3,4)

0 commit comments

Comments
 (0)