Skip to content

Commit

Permalink
Merge branch 'master' into binner_padder_patch
Browse files Browse the repository at this point in the history
Signed-off-by: Gemma Fardell <47746591+gfardell@users.noreply.github.com>
  • Loading branch information
gfardell authored Sep 27, 2023
2 parents 39ef31e + f5a9f97 commit a5beeef
Show file tree
Hide file tree
Showing 8 changed files with 320 additions and 180 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
- Add norm for CompositionOperator
- Refactor SIRT algorithm to make it more computationally and memory efficient
- Optimisation in L2NormSquared
- Added support for partitioner, when partitions have size 1
- Fix for show_geometry bug for 2D data
- FBP split processing bug fix - now respects panel origin set in geometry
- Binner/Padder/Slicer bug fix - now respects panel origin set in geometry
- Added warmstart capability to proximal evaluation of the CIL TotalVariation function.
- Tidied up documentation in the framework folder

* 23.0.1
- Fix bug with NikonReader requiring ROI to be set in constructor.
Expand Down
1 change: 1 addition & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Gemma Fardell (2019 - present) - 1
Kris Thielemans (2020 - present) - 5
Laura Murgatroyd (2021 - present) - 1
Evelina Ametova (2018-2020) - 3, (2020-2021) - 6
Margaret Duff (2023 - present) - 1

CIL Contributors:
Srikanth Nagella (2017-2018) - 1
Expand Down
40 changes: 20 additions & 20 deletions Wrappers/Python/cil/framework/BlockDataContainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class BlockDataContainer(object):
will fail
2) algebra between `BlockDataContainer`s and `list` or `numpy array` will
work as long as the number of `rows` and element of the arrays match,
indipendently on the fact that the `BlockDataContainer` could be nested
independently on the fact that the `BlockDataContainer` could be nested
3) algebra between `BlockDataContainer` and one `DataContainer` is possible.
It will require all the `DataContainers` in the block to be
compatible with the `DataContainer` we want to operate with.
Expand Down Expand Up @@ -147,7 +147,7 @@ def subtract(self, other, *args, **kwargs):
'''Algebra: subtract method of BlockDataContainer with number/DataContainer or BlockDataContainer
:param: other (number, DataContainer or subclasses or BlockDataContainer
:param: out (optional): provides a placehold for the resul.
:param: out (optional): provides a placeholder for the result.
'''
out = kwargs.get('out', None)
if out is not None:
Expand All @@ -157,8 +157,8 @@ def subtract(self, other, *args, **kwargs):
def multiply(self, other, *args, **kwargs):
'''Algebra: multiply method of BlockDataContainer with number/DataContainer or BlockDataContainer
:param: other (number, DataContainer or subclasses or BlockDataContainer
:param: out (optional): provides a placehold for the resul.
:param: other (number, DataContainer or subclasses or BlockDataContainer)
:param: out (optional): provides a placeholder for the result.
'''
out = kwargs.get('out', None)
if out is not None:
Expand All @@ -168,8 +168,8 @@ def multiply(self, other, *args, **kwargs):
def divide(self, other, *args, **kwargs):
'''Algebra: divide method of BlockDataContainer with number/DataContainer or BlockDataContainer
:param: other (number, DataContainer or subclasses or BlockDataContainer
:param: out (optional): provides a placehold for the resul.
:param: other (number, DataContainer or subclasses or BlockDataContainer)
:param: out (optional): provides a placeholder for the result.
'''
out = kwargs.get('out', None)
if out is not None:
Expand All @@ -180,7 +180,7 @@ def power(self, other, *args, **kwargs):
'''Algebra: power method of BlockDataContainer with number/DataContainer or BlockDataContainer
:param: other (number, DataContainer or subclasses or BlockDataContainer
:param: out (optional): provides a placehold for the resul.
:param: out (optional): provides a placeholder for the result.
'''
out = kwargs.get('out', None)
if out is not None:
Expand All @@ -190,8 +190,8 @@ def power(self, other, *args, **kwargs):
def maximum(self, other, *args, **kwargs):
'''Algebra: power method of BlockDataContainer with number/DataContainer or BlockDataContainer
:param: other (number, DataContainer or subclasses or BlockDataContainer
:param: out (optional): provides a placehold for the resul.
:param: other (number, DataContainer or subclasses or BlockDataContainer)
:param: out (optional): provides a placeholder for the result.
'''
out = kwargs.get('out', None)
if out is not None:
Expand All @@ -201,8 +201,8 @@ def maximum(self, other, *args, **kwargs):
def minimum(self, other, *args, **kwargs):
'''Algebra: power method of BlockDataContainer with number/DataContainer or BlockDataContainer
:param: other (number, DataContainer or subclasses or BlockDataContainer
:param: out (optional): provides a placehold for the resul.
:param: other (number, DataContainer or subclasses or BlockDataContainer)
:param: out (optional): provides a placeholder for the result.
'''
out = kwargs.get('out', None)
if out is not None:
Expand All @@ -224,14 +224,14 @@ def sapyb(self, a, y, b, out, num_threads = NUM_THREADS):
Example:
--------
a = 2
b = 3
ig = ImageGeometry(10,11)
x = ig.allocate(1)
y = ig.allocate(2)
bdc1 = BlockDataContainer(2*x, y)
bdc2 = BlockDataContainer(x, 2*y)
out = bdc1.sapyb(a,bdc2,b)
>>> a = 2
>>> b = 3
>>> ig = ImageGeometry(10,11)
>>> x = ig.allocate(1)
>>> y = ig.allocate(2)
>>> bdc1 = BlockDataContainer(2*x, y)
>>> bdc2 = BlockDataContainer(x, 2*y)
>>> out = bdc1.sapyb(a,bdc2,b)
'''
if out is None:
raise ValueError("out container cannot be None")
Expand All @@ -249,7 +249,7 @@ def binary_operations(self, operation, other, *args, **kwargs):
'''Algebra: generic method of algebric operation with BlockDataContainer with number/DataContainer or BlockDataContainer
Provides commutativity with DataContainer and subclasses, i.e. this
class's reverse algebric methods take precedence w.r.t. direct algebric
class's reverse algebraic methods take precedence w.r.t. direct algebraic
methods of DataContainer and subclasses.
This method is not to be used directly
Expand Down
39 changes: 18 additions & 21 deletions Wrappers/Python/cil/framework/framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ def _construct_BlockGeometry_from_indices(self, indices):
ag = self.geometry.copy()
ag.config.angles.angle_data = numpy.take(self.geometry.angles, mask, axis=0)
ags.append(ag)

return BlockGeometry(*ags)

def partition(self, num_batches, mode, seed=None):
Expand Down Expand Up @@ -200,8 +199,11 @@ def _partition_deterministic(self, num_batches, stagger=False, indices=None):

for i in range(num_batches):
out[i].fill(
numpy.take(self.array, partition_indices[i], axis=axis)
numpy.squeeze(
numpy.take(self.array, partition_indices[i], axis=axis)
)
)

return out

def _partition_random_permutation(self, num_batches, seed=None):
Expand Down Expand Up @@ -2153,7 +2155,6 @@ def shape(self):
AcquisitionGeometry.ANGLE: self.config.angles.num_positions,
AcquisitionGeometry.VERTICAL: self.config.panel.num_pixels[1],
AcquisitionGeometry.HORIZONTAL: self.config.panel.num_pixels[0]}

shape = []
for label in self.dimension_labels:
shape.append(shape_dict[label])
Expand Down Expand Up @@ -2992,12 +2993,12 @@ def __str__ (self, representation=False):
def get_data_axes_order(self,new_order=None):
'''returns the axes label of self as a list
if new_order is None returns the labels of the axes as a sorted-by-key list
if new_order is a list of length number_of_dimensions, returns a list
If new_order is None returns the labels of the axes as a sorted-by-key list.
If new_order is a list of length number_of_dimensions, returns a list
with the indices of the axes in new_order with respect to those in
self.dimension_labels: i.e.
self.dimension_labels = {0:'horizontal',1:'vertical'}
new_order = ['vertical','horizontal']
>>> self.dimension_labels = {0:'horizontal',1:'vertical'}
>>> new_order = ['vertical','horizontal']
returns [1,0]
'''
if new_order is None:
Expand Down Expand Up @@ -3125,19 +3126,18 @@ def sapyb(self, a, y, b, out=None, num_threads=NUM_THREADS):
out : return DataContainer, if None a new DataContainer is returned, default None.
out can be self or y.
num_threads : number of threads to use during the calculation, using the CIL C library
It will try to use the CIL C library and default to numpy operations, in case the C library does not handle the types.
It will try to use the CIL C library and default to numpy operations, in case the C library does
not handle the types.
Example:
Example
-------
a = 2
b = 3
ig = ImageGeometry(10,11)
x = ig.allocate(1)
y = ig.allocate(2)
out = x.sapyb(a,y,b)
>>> a = 2
>>> b = 3
>>> ig = ImageGeometry(10,11)
>>> x = ig.allocate(1)
>>> y = ig.allocate(2)
>>> out = x.sapyb(a,y,b)
'''
ret_out = False

Expand Down Expand Up @@ -3328,11 +3328,8 @@ def norm(self, **kwargs):
return numpy.sqrt(self.squared_norm(**kwargs))

def dot(self, other, *args, **kwargs):
'''return the inner product of 2 DataContainers viewed as vectors
applies to real and complex data. In such case the dot method returns
a.dot(b.conjugate())
'''returns the inner product of 2 DataContainers viewed as vectors. Suitable for real and complex data.
For complex data, the dot method returns a.dot(b.conjugate())
'''
method = kwargs.get('method', 'numpy')
if method not in ['numpy','reduce']:
Expand Down
Loading

0 comments on commit a5beeef

Please sign in to comment.