Skip to content

Commit

Permalink
Merge pull request #340 from GSTT-CSC/release/2.1.0
Browse files Browse the repository at this point in the history
Release/2.1.0
  • Loading branch information
Lucrezia-Cester authored Apr 18, 2023
2 parents 61f7c8f + ab962a0 commit 7f10989
Show file tree
Hide file tree
Showing 17 changed files with 107 additions and 26 deletions.
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ date-released: 2022-02-24
message: "If you use hazen in your work, please cite it using these metadata."
repository-code: "https://github.com/GSTT-CSC/hazen"
title: hazen
version: "1.1.4"
version: "1.2.0"
...
2 changes: 1 addition & 1 deletion hazenlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
'Measured_slice_width' is an optional argument for the SNR function.
'Log' is an optional argument that allows users to set the severity of the logs.
<task> snr | slice_position | slice_width | spatial_resolution | uniformity | ghosting | relaxometry | snr_map |
acr_ghosting | acr_uniformity |
acr_ghosting | acr_uniformity | acr_spatial_resolution | acr_slice_thickness | acr_snr | acr_slice_position | acr_geometric_accuracy
<folder>
--report
Expand Down
2 changes: 1 addition & 1 deletion hazenlib/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.1.4'
__version__ = '1.2.0'
9 changes: 9 additions & 0 deletions tests/test_acr_geometric_accuracy.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,20 @@ def test_object_centre(self):
def test_geo_accuracy_slice1(self):
slice1_vals = np.array(self.acr_geometric_accuracy_task.get_geometric_accuracy_slice1(self.dcm))
slice1_vals = np.round(slice1_vals, 2)

print("\ntest_geo_accuracy.py::TestGeoAccuracy::test_geo_accuracy_slice1")
print("new_release:", slice1_vals)
print("fixed value:", self.L1)

assert (slice1_vals == self.L1).all() == True

def test_geo_accuracy_slice5(self):
slice5_vals = np.array(self.acr_geometric_accuracy_task.get_geometric_accuracy_slice5(self.dcm2))
slice5_vals = np.round(slice5_vals, 2)

print("\ntest_geo_accuracy.py::TestGeoAccuracy::test_geo_accuracy_slice1")
print("new_release:", slice5_vals)
print("fixed value:", self.L5)
assert (slice5_vals == self.L5).all() == True

def test_rotate_point(self):
Expand Down
8 changes: 7 additions & 1 deletion tests/test_acr_ghosting.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ def test_object_centre(self):
assert self.acr_ghosting_task.centroid_com(self.dcm.pixel_array)[1] == self.centre

def test_ghosting(self):
assert round(self.acr_ghosting_task.get_signal_ghosting(self.dcm), 3) == self.psg
ghosting_val = round(self.acr_ghosting_task.get_signal_ghosting(self.dcm), 3)

print("\ntest_ghosting.py::TestGhosting::test_ghosting")
print("new_release_value:", ghosting_val)
print("fixed_value:", self.psg)

assert ghosting_val == self.psg


class TestACRGhostingGE(unittest.TestCase):
Expand Down
11 changes: 9 additions & 2 deletions tests/test_acr_slice_position.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,15 @@ def test_wedge_find(self):
self.y_pts[1]).all() == True

def test_slice_position(self):
assert round(self.acr_slice_position_task.get_slice_position(self.dcm_1), 2) == self.dL[0]
assert round(self.acr_slice_position_task.get_slice_position(self.dcm_11), 2) == self.dL[1]
slice_position_val_1 = round(self.acr_slice_position_task.get_slice_position(self.dcm_1), 2)
slice_position_val_11 = round(self.acr_slice_position_task.get_slice_position(self.dcm_11), 2)

print("\ntest_slice_position.py::TestSlicePosition::test_slice_position")
print("new_release_value:", slice_position_val_1)
print("fixed_value:", self.dL[0])

assert slice_position_val_1 == self.dL[0]
assert slice_position_val_11 == self.dL[1]


class TestACRSlicePositionGE(unittest.TestCase):
Expand Down
8 changes: 7 additions & 1 deletion tests/test_acr_slice_thickness.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ def test_ramp_find(self):
self.y_pts).all() == True

def test_slice_thickness(self):
assert round(self.acr_slice_thickness_task.get_slice_thickness(self.dcm), 2) == self.dz
slice_thickness_val = round(self.acr_slice_thickness_task.get_slice_thickness(self.dcm), 2)

print("\ntest_slice_thickness.py::TestSliceThickness::test_slice_thickness")
print("new_release_value:", slice_thickness_val)
print("fixed_value:", self.dz)

assert slice_thickness_val == self.dz


class TestACRSliceThicknessGE(unittest.TestCase):
Expand Down
8 changes: 7 additions & 1 deletion tests/test_acr_snr.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ def test_snr_by_smoothing(self):

def test_snr_by_subtraction(self):
snr, _ = self.acr_snr_task.snr_by_subtraction(self.dcm, self.dcm2)
assert round(snr, 2) == self.sub_snr
rounded_snr = round(snr, 2)

print("\ntest_snr_by_subtraction.py::TestSnrBySubtraction::test_snr_by_subtraction")
print("new_release_value:", rounded_snr)
print("fixed_value:", self.sub_snr)

assert rounded_snr == self.sub_snr


class TestACRSNRGE(unittest.TestCase):
Expand Down
7 changes: 6 additions & 1 deletion tests/test_acr_spatial_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,13 @@ def test_retrieve_slope(self):
self.edge_type[1])[0], 3) == self.slope

def test_get_MTF50(self):
assert self.acr_spatial_resolution_task.get_mtf50(self.dcm) == self.MTF50
mtf50_val = self.acr_spatial_resolution_task.get_mtf50(self.dcm)

print("\ntest_get_MTF50.py::TestGetMTF50::test_get_MTF50")
print("new_release_value:", mtf50_val)
print("fixed_value:", self.MTF50)

assert mtf50_val == self.MTF50

class TestACRSpatialResolutionGE(unittest.TestCase):
ACR_SPATIAL_RESOLUTION_DATA = pathlib.Path(TEST_DATA_DIR / 'acr')
Expand Down
8 changes: 7 additions & 1 deletion tests/test_acr_uniformity.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ def test_circular_mask(self):

def test_uniformity(self):
results = self.acr_uniformity_task.get_integral_uniformity(self.dcm)
assert round(results, 2) == self.piu
rounded_results = round(results, 2)

print("\ntest_uniformity.py::TestUniformity::test_uniformity")
print("new_release_values:", rounded_results)
print("fixed_values:", self.piu)

assert rounded_results == self.piu


# class TestACRUniformityPhilips(unittest.TestCase):
Expand Down
8 changes: 7 additions & 1 deletion tests/test_ghosting.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,13 @@ def test_get_ghost_slice(self):
assert list(self.ghosting.get_ghost_slice(self.SIGNAL_BOUNDING_BOX, self.dcm)[1]) == list(self.GHOST_SLICE[1])

def test_get_ghosting(self):
assert self.ghosting.get_ghosting(self.dcm) == self.GHOSTING
ghosting_val = self.ghosting.get_ghosting(self.dcm)

print("\ntest_get_ghosting.py::TestGetGhosting::test_get_ghosting")
print("new_release_value:", ghosting_val)
print("fixed_value:", self.GHOSTING)

assert ghosting_val == self.GHOSTING


class TestCOLPEGhosting(TestGhosting):
Expand Down
9 changes: 7 additions & 2 deletions tests/test_slice_position.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,14 @@ def test_get_rods_coords(self):

def test_slice_position(self):
results = self.hazen_slice_position.run()
key = self.hazen_slice_position.key(self.hazen_slice_position.data[0])
slice_positions = results[key]['slice_positions']

assert results[self.hazen_slice_position.key(self.hazen_slice_position.data[0])][
'slice_positions'] == self.SLICE_POSITION_OUTPUT
print("\ntest_slice_position.py::TestSlicePosition::test_slice_position")
print("new_release_value:", slice_positions)
print("fixed_value", self.SLICE_POSITION_OUTPUT)

assert slice_positions == self.SLICE_POSITION_OUTPUT


# now test on canon data
Expand Down
14 changes: 8 additions & 6 deletions tests/test_slice_width.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,12 +236,14 @@ def test_fit_trapezoid(self):

def test_slice_width(self):
results = self.slice_width.run()
self.slice_width.key(self.slice_width.data[0])
# key = f"{self.slice_width.data[0].SeriesDescription}_{self.slice_width.data[0].SeriesNumber}_{self.slice_width.data[0].InstanceNumber}"
# print("slice width")
# print(results[key]['slice_width_mm'])
# assert abs(results[key]['slice_width_mm'] - self.SW_MATLAB) < 0.1
assert abs(results[self.slice_width.key(self.slice_width.data[0])]['slice_width_mm'] - self.SW_MATLAB) < 0.1
key = self.slice_width.key(self.slice_width.data[0])
slice_width_mm = results[key]['slice_width_mm']

print("\ntest_slice_width.py::TestSliceWidth::test_slice_width")
print("new_release_value:", slice_width_mm)
print("fixed_value:", self.SW_MATLAB)

assert abs(slice_width_mm - self.SW_MATLAB) < 0.1


class Test512Matrix(TestSliceWidth):
Expand Down
3 changes: 3 additions & 0 deletions tests/test_snr.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ def test_get_object_centre(self):

def test_image_snr(self):
val = self.snr.run()
print("\ntest_snr.py::TestSnrThreshold::test_image_snr")
print("set values:", val)
print("new_release_values", self.snr.run())
self.assertTrue(self.LOWER_SMOOTHED_SNR <= val[self.snr.key(self.snr.data[0])][
f"snr_smoothing_normalised_{self.snr.key(self.snr.data[0])}"] <= self.UPPER_SMOOTHED_SNR)
self.assertTrue(self.LOWER_SUBTRACT_SNR <= val[self.snr.key(self.snr.data[0])][
Expand Down
9 changes: 7 additions & 2 deletions tests/test_snr_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,13 @@ def test_calc_snr(self):
self.snr_map.snr, 192.8818801790859)

def test_calc_snr_map(self):
np.testing.assert_almost_equal(
self.snr_map.snr_map.cumsum().sum(), 128077116718.40483)
snr_map_cumsum = self.snr_map.snr_map.cumsum().sum()

print("\ntest_calc_snr_map.py::TestCalcSnrMap::test_calc_snr_map")
print("new_release_value:", snr_map_cumsum)
print("fixed_value:", 128077116718.40483)

np.testing.assert_almost_equal(snr_map_cumsum, 128077116718.40483)

def test_plot_detailed(self):
# Just check a valid figure handle is returned
Expand Down
11 changes: 9 additions & 2 deletions tests/test_spatial_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,9 +415,16 @@ def test_mtf(self):

def test_calculate_mtf(self):
res = self.hazen_spatial_resolution.calculate_mtf(self.hazen_spatial_resolution.data[0])
assert res['frequency_encoding_direction'] == pytest.approx(self.MTF_FE)
assert res['phase_encoding_direction'] == pytest.approx(self.MTF_PE)
fe_res = res['frequency_encoding_direction']
pe_res = res['phase_encoding_direction']

print("\ntest_calculate_mtf.py::TestCalculateMtf::test_calculate_mtf")
print("new_release_value:", fe_res)
print("fixed_value:", self.MTF_FE)


assert fe_res == pytest.approx(self.MTF_FE)
assert pe_res == pytest.approx(self.MTF_PE)

class TestPhilipsResolution(TestSpatialResolution):
RESOLUTION_DATA = pathlib.Path(TEST_DATA_DIR / 'resolution')
Expand Down
14 changes: 11 additions & 3 deletions tests/test_uniformity.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,18 @@ def setUp(self):

def test_uniformity(self):
results = self.uniformity_task.run()
assert results[self.uniformity_task.key(self.uniformity_task.data[0])]['horizontal'][
'IPEM'] == self.IPEM_HORIZONTAL
assert results[self.uniformity_task.key(self.uniformity_task.data[0])]['vertical']['IPEM'] == self.IPEM_VERTICAL
key = self.uniformity_task.key(self.uniformity_task.data[0])
horizontal_ipem = results[key]['horizontal']['IPEM']
vertical_ipem = results[key]['vertical']['IPEM']

print("\ntest_uniformity.py::TestUniformity::test_uniformity")

print("new_release_value:", vertical_ipem)

print("fixed_value:", self.IPEM_VERTICAL)

assert horizontal_ipem == self.IPEM_HORIZONTAL
assert vertical_ipem == self.IPEM_VERTICAL

class TestSagUniformity(TestUniformity):
IPEM_HORIZONTAL = 0.46875
Expand Down

4 comments on commit 7f10989

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
hazenlib
   HazenTask.py25388%32–34
   __init__.py1514173%141, 145, 155, 160, 197, 204–209, 220, 223–230, 250–252, 270–272, 291–293, 302, 307, 313, 363, 374, 380–386, 400–401, 405
   exceptions.py21481%17–21
   relaxometry.py3179072%238–256, 631, 690–692, 746, 794–816, 834–849, 1174–1177, 1186–1189, 1201–1214, 1217–1222, 1233–1263
   shapes.py20955%13, 16, 24–29, 32
   tools.py84890%43–50, 92, 101, 117
hazenlib/tasks
   acr_geometric_accuracy.py1455562%38–72, 176–192, 206–230
   acr_ghosting.py1164264%33–53, 91–93, 123–125, 161–194
   acr_slice_position.py1545366%53–74, 152, 213–258
   acr_slice_thickness.py1536359%40–60, 186–241
   acr_snr.py1375858%34–71, 96, 165–175, 208–221, 254–267
   acr_spatial_resolution.py2427270%66–86, 165, 208, 221–230, 319–374
   acr_uniformity.py893264%34–54, 121–138
   ghosting.py1505166%18–32, 47, 109–110, 114, 124–125, 151–153, 170–172, 218–256
   relaxometry.py7271%10–11
   slice_position.py1182281%31, 40–41, 103–104, 130, 210, 217–234
   slice_width.py3565285%34–37, 107, 166–186, 451, 456–457, 463, 468, 530–531, 780–821
   snr.py1636660%62–67, 161–179, 194–203, 221–231, 258–268, 273–283, 314–327, 332–340, 369–382
   snr_map.py106199%294
   spatial_resolution.py2464482%36–39, 62, 147, 206, 332–368
   uniformity.py781976%42–45, 91–92, 99, 133–147
TOTAL289478773% 

Tests Skipped Failures Errors Time
219 0 💤 0 ❌ 0 🔥 2m 31s ⏱️

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
hazenlib
   HazenTask.py26388%32–34
   __init__.py1514173%141, 145, 155, 160, 197, 204–209, 220, 223–230, 250–252, 270–272, 291–293, 302, 307, 313, 363, 374, 380–386, 400–401, 405
   exceptions.py21481%17–21
   relaxometry.py3179072%238–256, 631, 690–692, 746, 794–816, 834–849, 1174–1177, 1186–1189, 1201–1214, 1217–1222, 1233–1263
   shapes.py20955%13, 16, 24–29, 32
   tools.py84890%43–50, 92, 101, 117
hazenlib/tasks
   acr_geometric_accuracy.py1455562%38–72, 176–192, 206–230
   acr_ghosting.py1164264%33–53, 91–93, 123–125, 161–194
   acr_slice_position.py1545366%53–74, 152, 213–258
   acr_slice_thickness.py1536359%40–60, 186–241
   acr_snr.py1375858%34–71, 96, 165–175, 208–221, 254–267
   acr_spatial_resolution.py2427270%66–86, 165, 208, 221–230, 319–374
   acr_uniformity.py893264%34–54, 121–138
   ghosting.py1505166%18–32, 47, 109–110, 114, 124–125, 151–153, 170–172, 218–256
   relaxometry.py7271%10–11
   slice_position.py1182281%31, 40–41, 103–104, 130, 210, 217–234
   slice_width.py3595286%34–37, 107, 166–186, 451, 456–457, 463, 468, 530–531, 780–821
   snr.py1636660%62–67, 161–179, 194–203, 221–231, 258–268, 273–283, 314–327, 332–340, 369–382
   snr_map.py106199%294
   spatial_resolution.py2474482%36–39, 62, 147, 206, 332–368
   uniformity.py781976%42–45, 91–92, 99, 133–147
TOTAL289978773% 

Tests Skipped Failures Errors Time
219 0 💤 0 ❌ 0 🔥 2m 50s ⏱️

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
hazenlib
   HazenTask.py25388%32–34
   __init__.py1514173%141, 145, 155, 160, 197, 204–209, 220, 223–230, 250–252, 270–272, 291–293, 302, 307, 313, 363, 374, 380–386, 400–401, 405
   exceptions.py21481%17–21
   relaxometry.py3179072%238–256, 631, 690–692, 746, 794–816, 834–849, 1174–1177, 1186–1189, 1201–1214, 1217–1222, 1233–1263
   shapes.py20955%13, 16, 24–29, 32
   tools.py84890%43–50, 92, 101, 117
hazenlib/tasks
   acr_geometric_accuracy.py1455562%38–72, 176–192, 206–230
   acr_ghosting.py1164264%33–53, 91–93, 123–125, 161–194
   acr_slice_position.py1545366%53–74, 152, 213–258
   acr_slice_thickness.py1536359%40–60, 186–241
   acr_snr.py1375858%34–71, 96, 165–175, 208–221, 254–267
   acr_spatial_resolution.py2427270%66–86, 165, 208, 221–230, 319–374
   acr_uniformity.py893264%34–54, 121–138
   ghosting.py1505166%18–32, 47, 109–110, 114, 124–125, 151–153, 170–172, 218–256
   relaxometry.py7271%10–11
   slice_position.py1182281%31, 40–41, 103–104, 130, 210, 217–234
   slice_width.py3565285%34–37, 107, 166–186, 451, 456–457, 463, 468, 530–531, 780–821
   snr.py1636660%62–67, 161–179, 194–203, 221–231, 258–268, 273–283, 314–327, 332–340, 369–382
   snr_map.py106199%294
   spatial_resolution.py2464482%36–39, 62, 147, 206, 332–368
   uniformity.py781976%42–45, 91–92, 99, 133–147
TOTAL289478773% 

Tests Skipped Failures Errors Time
219 0 💤 0 ❌ 0 🔥 2m 31s ⏱️

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
hazenlib
   HazenTask.py26388%32–34
   __init__.py1514173%141, 145, 155, 160, 197, 204–209, 220, 223–230, 250–252, 270–272, 291–293, 302, 307, 313, 363, 374, 380–386, 400–401, 405
   exceptions.py21481%17–21
   relaxometry.py3179072%238–256, 631, 690–692, 746, 794–816, 834–849, 1174–1177, 1186–1189, 1201–1214, 1217–1222, 1233–1263
   shapes.py20955%13, 16, 24–29, 32
   tools.py84890%43–50, 92, 101, 117
hazenlib/tasks
   acr_geometric_accuracy.py1455562%38–72, 176–192, 206–230
   acr_ghosting.py1164264%33–53, 91–93, 123–125, 161–194
   acr_slice_position.py1545366%53–74, 152, 213–258
   acr_slice_thickness.py1536359%40–60, 186–241
   acr_snr.py1375858%34–71, 96, 165–175, 208–221, 254–267
   acr_spatial_resolution.py2427270%66–86, 165, 208, 221–230, 319–374
   acr_uniformity.py893264%34–54, 121–138
   ghosting.py1505166%18–32, 47, 109–110, 114, 124–125, 151–153, 170–172, 218–256
   relaxometry.py7271%10–11
   slice_position.py1182281%31, 40–41, 103–104, 130, 210, 217–234
   slice_width.py3595286%34–37, 107, 166–186, 451, 456–457, 463, 468, 530–531, 780–821
   snr.py1636660%62–67, 161–179, 194–203, 221–231, 258–268, 273–283, 314–327, 332–340, 369–382
   snr_map.py106199%294
   spatial_resolution.py2474482%36–39, 62, 147, 206, 332–368
   uniformity.py781976%42–45, 91–92, 99, 133–147
TOTAL289978773% 

Tests Skipped Failures Errors Time
219 0 💤 0 ❌ 0 🔥 3m 7s ⏱️

Please sign in to comment.