-
Notifications
You must be signed in to change notification settings - Fork 70
Image Geometry get_slice returns IG with offset centre #2235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
ba301fb
962d2af
4b64825
be94d8e
c1363c8
5d861ba
5af89fe
06d92df
1935528
5d393a4
991384c
a0873f8
8ad816b
e5ff5dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -174,27 +174,65 @@ def __init__(self, | |||||||||||||||
|
|
||||||||||||||||
| def get_slice(self,channel=None, vertical=None, horizontal_x=None, horizontal_y=None): | ||||||||||||||||
| ''' | ||||||||||||||||
| Returns a new ImageGeometry of a single slice of in the requested direction. | ||||||||||||||||
| Returns a new ImageGeometry of a single slice in the requested direction. | ||||||||||||||||
|
|
||||||||||||||||
| Parameters | ||||||||||||||||
| ---------- | ||||||||||||||||
| channel : int or 'centre', optional | ||||||||||||||||
| The channel index to slice. Default is None (no slicing). | ||||||||||||||||
| vertical : int or 'centre', optional | ||||||||||||||||
| The vertical index to slice. Default is None (no slicing). | ||||||||||||||||
| horizontal_x : int, optional | ||||||||||||||||
| The horizontal x index to slice. Default is None (no slicing). | ||||||||||||||||
| horizontal_y : int, optional | ||||||||||||||||
| The horizontal y index to slice. Default is None (no slicing). | ||||||||||||||||
| Returns | ||||||||||||||||
| ------- | ||||||||||||||||
| geometry_new : ImageGeometry | ||||||||||||||||
| A new ImageGeometry object representing the sliced geometry. | ||||||||||||||||
|
|
||||||||||||||||
| Note | ||||||||||||||||
| ---- | ||||||||||||||||
| Slicing on vertical with 'centre' will return the central slice in that dimension. | ||||||||||||||||
| Slicing on channels returns a geometry with a single channel, however the channel label is not | ||||||||||||||||
| typically stored in the geometry. | ||||||||||||||||
| ''' | ||||||||||||||||
|
|
||||||||||||||||
| geometry_new = self.copy() | ||||||||||||||||
| if channel is not None: | ||||||||||||||||
| geometry_new.channels = 1 | ||||||||||||||||
|
|
||||||||||||||||
| try: | ||||||||||||||||
| geometry_new.channel_labels = [self.channel_labels[channel]] | ||||||||||||||||
| except: | ||||||||||||||||
| geometry_new.channel_labels = None | ||||||||||||||||
|
|
||||||||||||||||
| if vertical is not None: | ||||||||||||||||
| geometry_new.voxel_num_z = 0 | ||||||||||||||||
| geometry_new.voxel_num_z = 1 | ||||||||||||||||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note this does not mean the shape is 1 in this dimension: CIL/Wrappers/Python/cil/framework/image_geometry.py Lines 101 to 107 in 8ad816b
|
||||||||||||||||
| if vertical != 'centre': | ||||||||||||||||
| if vertical == 0: | ||||||||||||||||
| warnings.warn("Slicing vertical at index 0 results in a geometry \ | ||||||||||||||||
| offset along the vertical axis. If you do not require an offset ImageGeometry, set vertical='centre", | ||||||||||||||||
| UserWarning) | ||||||||||||||||
|
Comment on lines
+212
to
+215
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gfardell - this is what we decided on previously - to raise a warning if they set vertical=0 |
||||||||||||||||
| voxel_offset = (self.voxel_num_z)/2 - (vertical+0.5) | ||||||||||||||||
| geometry_new.center_z -= voxel_offset * geometry_new.voxel_size_z | ||||||||||||||||
|
|
||||||||||||||||
| if horizontal_y is not None: | ||||||||||||||||
| geometry_new.voxel_num_y = 0 | ||||||||||||||||
| geometry_new.voxel_num_y = 1 | ||||||||||||||||
| voxel_offset = (self.voxel_num_y)/2 - (horizontal_y +0.5) | ||||||||||||||||
| geometry_new.center_y -= voxel_offset * geometry_new.voxel_size_y | ||||||||||||||||
|
|
||||||||||||||||
| if horizontal_x is not None: | ||||||||||||||||
| geometry_new.voxel_num_x = 0 | ||||||||||||||||
| geometry_new.voxel_num_x = 1 | ||||||||||||||||
| voxel_offset = (self.voxel_num_x)/2 - (horizontal_x+0.5) | ||||||||||||||||
| geometry_new.center_x -= voxel_offset * geometry_new.voxel_size_x | ||||||||||||||||
|
|
||||||||||||||||
| return geometry_new | ||||||||||||||||
|
|
||||||||||||||||
| def get_centre_slice(self): | ||||||||||||||||
| ''' | ||||||||||||||||
| Returns a new ImageGeometry of the centre slice in the vertical direction. | ||||||||||||||||
| ''' | ||||||||||||||||
| return self.get_slice(vertical='centre') | ||||||||||||||||
|
|
||||||||||||||||
| def get_order_by_label(self, dimension_labels, default_dimension_labels): | ||||||||||||||||
| order = [] | ||||||||||||||||
|
|
||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| # Copyright 2025 United Kingdom Research and Innovation | ||
| # Copyright 2025 The University of Manchester | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| # | ||
| # Authors: | ||
| # CIL Developers, listed at: https://github.com/TomographicImaging/CIL/blob/master/NOTICE.txt | ||
|
|
||
| import unittest | ||
| from utils import initialise_tests | ||
| from cil.framework import ImageGeometry | ||
| from cil.framework.labels import ImageDimension | ||
|
|
||
| initialise_tests() | ||
|
|
||
|
|
||
| class TestImageGeometry(unittest.TestCase): | ||
| def setUp(self): | ||
| self.ig = ImageGeometry(2,3,4,channels=5) | ||
|
|
||
| # get_slice tests --------------------------------------------------------------------------------------------------------------- | ||
|
|
||
| def test_get_slice_vertical(self): | ||
| non_default_dimension_labels = [ImageDimension["HORIZONTAL_X"], ImageDimension["CHANNEL"], ImageDimension["HORIZONTAL_Y"], | ||
| ImageDimension["VERTICAL"]] | ||
| ig = self.ig.copy() | ||
| ig.set_labels(non_default_dimension_labels) | ||
| ig.voxel_size_z = 5.5 | ||
| sub = ig.get_slice(vertical = 1) | ||
| self.assertTrue( sub.shape == (2,5,3)) | ||
| self.assertEqual(sub.voxel_size_z,5.5) | ||
| self.assertEqual(sub.center_x,0) | ||
| self.assertEqual(sub.center_y,0) | ||
| self.assertEqual(sub.center_z,-0.5*sub.voxel_size_z) | ||
|
|
||
| def test_get_slice_vertical_centre(self): | ||
| non_default_dimension_labels = [ImageDimension["HORIZONTAL_X"], ImageDimension["CHANNEL"], ImageDimension["HORIZONTAL_Y"], | ||
| ImageDimension["VERTICAL"]] | ||
| self.ig.set_labels(non_default_dimension_labels) | ||
| sub = self.ig.get_slice(vertical = 'centre') | ||
| self.assertTrue( sub.shape == (2,5,3)) | ||
| self.assertEqual(sub.center_x,0) | ||
| self.assertEqual(sub.center_y,0) | ||
| self.assertEqual(sub.center_z,0) | ||
|
|
||
|
|
||
| def test_get_slice_horizontal_x(self): | ||
| non_default_dimension_labels = [ImageDimension["HORIZONTAL_X"], ImageDimension["CHANNEL"], ImageDimension["HORIZONTAL_Y"], | ||
| ImageDimension["VERTICAL"]] | ||
| self.ig.set_labels(non_default_dimension_labels) | ||
| sub = self.ig.get_slice(horizontal_x = 1) | ||
| self.assertTrue(sub.shape == (5,3,4)) | ||
| self.assertEqual(sub.center_x,0.5) | ||
| self.assertEqual(sub.center_y,0) | ||
| self.assertEqual(sub.center_z,0) | ||
|
|
||
|
|
||
| def test_get_slice_channel(self): | ||
| non_default_dimension_labels = [ImageDimension["HORIZONTAL_X"], ImageDimension["CHANNEL"], ImageDimension["HORIZONTAL_Y"], | ||
| ImageDimension["VERTICAL"]] | ||
| self.ig.set_labels(non_default_dimension_labels) | ||
| sub = self.ig.get_slice(channel = 1) | ||
| self.assertTrue(sub.shape == (2,3,4)) | ||
| self.assertTrue(sub.channels == 1) | ||
|
|
||
| def test_get_slice_channel_centre(self): | ||
| non_default_dimension_labels = [ImageDimension["HORIZONTAL_X"], ImageDimension["CHANNEL"], ImageDimension["HORIZONTAL_Y"], | ||
| ImageDimension["VERTICAL"]] | ||
| self.ig.set_labels(non_default_dimension_labels) | ||
| sub = self.ig.get_slice(channel = 'centre') | ||
| self.assertTrue(sub.shape == (2,3,4)) | ||
| self.assertTrue(sub.channels == 1) | ||
|
|
||
| def test_get_slice_horizontal_y(self): | ||
| non_default_dimension_labels = [ImageDimension["HORIZONTAL_X"], ImageDimension["HORIZONTAL_Y"]] | ||
| self.ig.set_labels(non_default_dimension_labels) | ||
| sub = self.ig.get_slice(horizontal_y = 0) | ||
| self.assertTrue( sub.shape == (2,)) | ||
| self.assertEqual(sub.center_x,0) | ||
| self.assertEqual(sub.center_y,-1) | ||
| self.assertEqual(sub.center_z,0) | ||
|
|
||
| def test_get_slice_horizontal_x_and_horizontal_y(self): | ||
| sub = self.ig.get_slice(horizontal_x=0,horizontal_y=0) | ||
| self.assertTrue( sub.shape == (5,4)) | ||
|
|
||
| # test get_centre_slice --------------------------------------------------------------------------------------------------------------- | ||
|
|
||
| def test_get_centre_slice(self): | ||
| sub = self.ig.get_centre_slice() | ||
| sub2 = self.ig.get_slice(vertical='centre') | ||
| self.assertTrue( sub == sub2) | ||
|
|
||
| # ------------------------------------------------------------------------------------------------------------------------------- | ||
|
|
||
| def test_shape_change_with_new_labels(self): | ||
| new_dimension_labels = [ImageDimension["HORIZONTAL_Y"], ImageDimension["CHANNEL"], ImageDimension["VERTICAL"], ImageDimension["HORIZONTAL_X"]] | ||
| self.ig.set_labels(new_dimension_labels) | ||
| self.assertTrue( self.ig.shape == (3,5,4,2)) |
Uh oh!
There was an error while loading. Please reload this page.