retuve.hip_us.classes.general
Contains the Hip Data Classes and the Landmarks Class.
1# Copyright 2024 Adam McArthur 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15""" 16Contains the Hip Data Classes and the Landmarks Class. 17""" 18 19from typing import Dict, List, Tuple, Union 20 21from moviepy.video.io.ImageSequenceClip import ImageSequenceClip 22from plotly.graph_objs import Figure 23from radstract.data.nifti import NIFTI 24 25from retuve.classes.general import RecordedError 26from retuve.classes.metrics import Metric2D, Metric3D 27from retuve.hip_us.classes.dev import DevMetricsUS 28from retuve.hip_us.classes.enums import Side 29from retuve.keyphrases.config import Config 30 31 32class LandmarksUS: 33 """ 34 Class to store the landmarks of the Hip Ultrasound. 35 36 These are related to a standard graf image of a Hip. 37 38 :attr left: tuple: Left landmark 39 :attr right: tuple: Right landmark 40 :attr apex: tuple: Apex landmark 41 :attr point_D: tuple: Point D landmark 42 :attr point_d: tuple: Point d landmark 43 :attr mid_cov_point: tuple: Mid cov point landmark 44 """ 45 46 def __init__( 47 self, 48 left: Tuple[int, int] = None, 49 right: Tuple[int, int] = None, 50 apex: Tuple[int, int] = None, 51 point_D: Tuple[int, int] = None, 52 point_d: Tuple[int, int] = None, 53 mid_cov_point: Tuple[int, int] = None, 54 ): 55 self.left = left 56 self.right = right 57 self.apex = apex 58 self.point_D = point_D 59 self.point_d = point_d 60 self.mid_cov_point = mid_cov_point 61 62 def __iter__(self) -> Tuple: 63 return iter( 64 ( 65 self.left, 66 self.right, 67 self.apex, 68 self.point_D, 69 self.point_d, 70 self.mid_cov_point, 71 ) 72 ) 73 74 def items(self) -> Dict[str, Tuple]: 75 return { 76 "left": self.left, 77 "right": self.right, 78 "apex": self.apex, 79 "point_D": self.point_D, 80 "point_d": self.point_d, 81 "mid_cov_point": self.mid_cov_point, 82 }.items() 83 84 def __setitem__(self, key: str, value: Tuple[int, int]): 85 # use setattr to avoid infinite recursion 86 setattr(self, key, value) 87 88 def __repr__(self) -> str: 89 return ( 90 f"LandmarksUS({self.left}, {self.right}, {self.apex}, " 91 f"{self.point_D}, {self.point_d}, {self.mid_cov_point})" 92 ) 93 94 def to_dict(self) -> Dict[str, Tuple[int, int]]: 95 """ 96 Returns the landmarks as a dictionary. 97 """ 98 return { 99 "left": self.left, 100 "right": self.right, 101 "apex": self.apex, 102 "point_D": self.point_D, 103 "point_d": self.point_d, 104 "mid_cov_point": self.mid_cov_point, 105 } 106 107 108class HipDataUS: 109 """ 110 Class to store the Hip Data of a single Hip Image. 111 112 :attr landmarks: LandmarksUS: Landmarks of the Hip Image. 113 :attr metrics: List[Metric2D]: List of 2D Metrics. 114 :attr frame_no: int: Frame number of the Hip Image. 115 :attr side: Side: Side of the Hip Image. 116 """ 117 118 def __init__( 119 self, 120 landmarks: LandmarksUS = None, 121 metrics: List[Metric2D] = None, 122 frame_no: int = None, 123 side: Side = None, 124 ): 125 self.landmarks = landmarks 126 self.frame_no = frame_no 127 self.side = side 128 129 self.metrics = metrics 130 131 def __str__(self) -> str: 132 return ( 133 f"HipDataUS(landmarks={self.landmarks}, metrics={self.metrics}, " 134 f"frame_no={self.frame_no}, side={self.side})" 135 ) 136 137 def marked(self) -> bool: 138 """ 139 Returns whether the Hip Image has any non-zero metrics. 140 """ 141 if self.metrics is None: 142 return False 143 144 return any(metric.value != 0 for metric in self.metrics) 145 146 def get_metric(self, name: str) -> float: 147 """ 148 Returns the value of a metric by its name. 149 """ 150 if self.metrics is None: 151 return 0 152 153 for metric in self.metrics: 154 if metric.name == name: 155 return metric.value 156 return 0 157 158 def json_dump(self, config: Config, dev_metrics: DevMetricsUS): 159 """ 160 Returns a dictionary of the Hip Data in JSON format. 161 162 Used for saving the Hip Data to a JSON file or returning it from an API call. 163 164 :param config: Config object. 165 :param dev_metrics: DevMetricsUS object. 166 167 :return: Dictionary of the Hip Data in JSON format. 168 """ 169 170 return { 171 "metrics": [ 172 {metric.name: metric.value} for metric in self.metrics 173 ], 174 "keyphrase": config.name, 175 "dev_metrics": dev_metrics.json_dump(), 176 } 177 178 179class HipDatasUS: 180 """ 181 Class to store the Hip Data of multiple Hip Images. 182 183 :attr recorded_error: RecordedError: Recorded Error of the Hip Data. 184 :attr hip_datas: List[HipDataUS]: List of Hip Data. 185 :attr metrics: List[Metric3D]: List of 3D Metrics. 186 :attr graf_frame: int: Frame where the Graf angle is calculated. 187 :attr grafs_hip: HipDataUS: Hip Data where the Graf angle is calculated. 188 :attr dev_metrics: DevMetricsUS: Development Metrics of the Hip Data. 189 :attr video_clip: ImageSequenceClip: Video Clip of the Hip Data. 190 :attr visual_3d: Figure: 3D Visualization of the Hip Data. 191 :attr nifti: NIFTI: NIFTI object of the Hip Data. 192 :attr cr_points: List[float]: List of critical points detected. 193 """ 194 195 def __init__( 196 self, 197 ): 198 self.recorded_error: RecordedError = RecordedError() 199 200 self.hip_datas: List[HipDataUS] = [] 201 202 self.metrics: List[Metric3D] = [] 203 204 self.graf_frame: int = None 205 self.grafs_hip: HipDataUS = None 206 self.dev_metrics: DevMetricsUS = None 207 self.video_clip: ImageSequenceClip = None 208 self.visual_3d: Figure = None 209 self.nifti: NIFTI = None 210 self.cr_points: List[float] = [] 211 212 def __iter__(self) -> HipDataUS: 213 return iter(self.hip_datas) 214 215 def __getitem__(self, index) -> HipDataUS: 216 return self.hip_datas[index] 217 218 def __setitem__(self, index, value): 219 self.hip_datas[index] = value 220 221 def __len__(self): 222 return len(self.hip_datas) 223 224 def __str__(self): 225 output = "" 226 for hip_data in self.hip_datas: 227 output += f"{hip_data}\n" 228 229 return output 230 231 def append(self, hip_data: HipDataUS): 232 """ 233 Append a HipDataUS object to the HipDatasUS object. 234 """ 235 self.hip_datas.append(hip_data) 236 237 def sorted_metrics(self) -> List[Metric3D]: 238 """ 239 Returns the metrics sorted by name. 240 """ 241 return sorted(self.metrics, key=lambda metric: metric.name) 242 243 def json_dump(self, config: Config) -> Dict[str, Union[dict, str]]: 244 """ 245 Returns a dictionary of the Hip Datas in JSON format. 246 247 Used for saving the Hip Datas to a JSON file or returning it from an API call. 248 249 :param config: Config object. 250 251 :return: Dictionary of the Hip Datas in JSON format. 252 """ 253 return { 254 "metrics": [ 255 {metric.dump()[0]: metric.dump()[1:]} 256 for metric in self.metrics 257 ], 258 "graf_frame": self.graf_frame, 259 "dev_metrics": ( 260 self.dev_metrics.json_dump() if self.dev_metrics else None 261 ), 262 "recorded_error": str(self.recorded_error), 263 "keyphrase": config.name, 264 }
33class LandmarksUS: 34 """ 35 Class to store the landmarks of the Hip Ultrasound. 36 37 These are related to a standard graf image of a Hip. 38 39 :attr left: tuple: Left landmark 40 :attr right: tuple: Right landmark 41 :attr apex: tuple: Apex landmark 42 :attr point_D: tuple: Point D landmark 43 :attr point_d: tuple: Point d landmark 44 :attr mid_cov_point: tuple: Mid cov point landmark 45 """ 46 47 def __init__( 48 self, 49 left: Tuple[int, int] = None, 50 right: Tuple[int, int] = None, 51 apex: Tuple[int, int] = None, 52 point_D: Tuple[int, int] = None, 53 point_d: Tuple[int, int] = None, 54 mid_cov_point: Tuple[int, int] = None, 55 ): 56 self.left = left 57 self.right = right 58 self.apex = apex 59 self.point_D = point_D 60 self.point_d = point_d 61 self.mid_cov_point = mid_cov_point 62 63 def __iter__(self) -> Tuple: 64 return iter( 65 ( 66 self.left, 67 self.right, 68 self.apex, 69 self.point_D, 70 self.point_d, 71 self.mid_cov_point, 72 ) 73 ) 74 75 def items(self) -> Dict[str, Tuple]: 76 return { 77 "left": self.left, 78 "right": self.right, 79 "apex": self.apex, 80 "point_D": self.point_D, 81 "point_d": self.point_d, 82 "mid_cov_point": self.mid_cov_point, 83 }.items() 84 85 def __setitem__(self, key: str, value: Tuple[int, int]): 86 # use setattr to avoid infinite recursion 87 setattr(self, key, value) 88 89 def __repr__(self) -> str: 90 return ( 91 f"LandmarksUS({self.left}, {self.right}, {self.apex}, " 92 f"{self.point_D}, {self.point_d}, {self.mid_cov_point})" 93 ) 94 95 def to_dict(self) -> Dict[str, Tuple[int, int]]: 96 """ 97 Returns the landmarks as a dictionary. 98 """ 99 return { 100 "left": self.left, 101 "right": self.right, 102 "apex": self.apex, 103 "point_D": self.point_D, 104 "point_d": self.point_d, 105 "mid_cov_point": self.mid_cov_point, 106 }
Class to store the landmarks of the Hip Ultrasound.
These are related to a standard graf image of a Hip.
:attr left: tuple: Left landmark :attr right: tuple: Right landmark :attr apex: tuple: Apex landmark :attr point_D: tuple: Point D landmark :attr point_d: tuple: Point d landmark :attr mid_cov_point: tuple: Mid cov point landmark
47 def __init__( 48 self, 49 left: Tuple[int, int] = None, 50 right: Tuple[int, int] = None, 51 apex: Tuple[int, int] = None, 52 point_D: Tuple[int, int] = None, 53 point_d: Tuple[int, int] = None, 54 mid_cov_point: Tuple[int, int] = None, 55 ): 56 self.left = left 57 self.right = right 58 self.apex = apex 59 self.point_D = point_D 60 self.point_d = point_d 61 self.mid_cov_point = mid_cov_point
95 def to_dict(self) -> Dict[str, Tuple[int, int]]: 96 """ 97 Returns the landmarks as a dictionary. 98 """ 99 return { 100 "left": self.left, 101 "right": self.right, 102 "apex": self.apex, 103 "point_D": self.point_D, 104 "point_d": self.point_d, 105 "mid_cov_point": self.mid_cov_point, 106 }
Returns the landmarks as a dictionary.
109class HipDataUS: 110 """ 111 Class to store the Hip Data of a single Hip Image. 112 113 :attr landmarks: LandmarksUS: Landmarks of the Hip Image. 114 :attr metrics: List[Metric2D]: List of 2D Metrics. 115 :attr frame_no: int: Frame number of the Hip Image. 116 :attr side: Side: Side of the Hip Image. 117 """ 118 119 def __init__( 120 self, 121 landmarks: LandmarksUS = None, 122 metrics: List[Metric2D] = None, 123 frame_no: int = None, 124 side: Side = None, 125 ): 126 self.landmarks = landmarks 127 self.frame_no = frame_no 128 self.side = side 129 130 self.metrics = metrics 131 132 def __str__(self) -> str: 133 return ( 134 f"HipDataUS(landmarks={self.landmarks}, metrics={self.metrics}, " 135 f"frame_no={self.frame_no}, side={self.side})" 136 ) 137 138 def marked(self) -> bool: 139 """ 140 Returns whether the Hip Image has any non-zero metrics. 141 """ 142 if self.metrics is None: 143 return False 144 145 return any(metric.value != 0 for metric in self.metrics) 146 147 def get_metric(self, name: str) -> float: 148 """ 149 Returns the value of a metric by its name. 150 """ 151 if self.metrics is None: 152 return 0 153 154 for metric in self.metrics: 155 if metric.name == name: 156 return metric.value 157 return 0 158 159 def json_dump(self, config: Config, dev_metrics: DevMetricsUS): 160 """ 161 Returns a dictionary of the Hip Data in JSON format. 162 163 Used for saving the Hip Data to a JSON file or returning it from an API call. 164 165 :param config: Config object. 166 :param dev_metrics: DevMetricsUS object. 167 168 :return: Dictionary of the Hip Data in JSON format. 169 """ 170 171 return { 172 "metrics": [ 173 {metric.name: metric.value} for metric in self.metrics 174 ], 175 "keyphrase": config.name, 176 "dev_metrics": dev_metrics.json_dump(), 177 }
Class to store the Hip Data of a single Hip Image.
:attr landmarks: LandmarksUS: Landmarks of the Hip Image. :attr metrics: List[Metric2D]: List of 2D Metrics. :attr frame_no: int: Frame number of the Hip Image. :attr side: Side: Side of the Hip Image.
138 def marked(self) -> bool: 139 """ 140 Returns whether the Hip Image has any non-zero metrics. 141 """ 142 if self.metrics is None: 143 return False 144 145 return any(metric.value != 0 for metric in self.metrics)
Returns whether the Hip Image has any non-zero metrics.
147 def get_metric(self, name: str) -> float: 148 """ 149 Returns the value of a metric by its name. 150 """ 151 if self.metrics is None: 152 return 0 153 154 for metric in self.metrics: 155 if metric.name == name: 156 return metric.value 157 return 0
Returns the value of a metric by its name.
159 def json_dump(self, config: Config, dev_metrics: DevMetricsUS): 160 """ 161 Returns a dictionary of the Hip Data in JSON format. 162 163 Used for saving the Hip Data to a JSON file or returning it from an API call. 164 165 :param config: Config object. 166 :param dev_metrics: DevMetricsUS object. 167 168 :return: Dictionary of the Hip Data in JSON format. 169 """ 170 171 return { 172 "metrics": [ 173 {metric.name: metric.value} for metric in self.metrics 174 ], 175 "keyphrase": config.name, 176 "dev_metrics": dev_metrics.json_dump(), 177 }
Returns a dictionary of the Hip Data in JSON format.
Used for saving the Hip Data to a JSON file or returning it from an API call.
Parameters
- config: Config object.
- dev_metrics: DevMetricsUS object.
Returns
Dictionary of the Hip Data in JSON format.
180class HipDatasUS: 181 """ 182 Class to store the Hip Data of multiple Hip Images. 183 184 :attr recorded_error: RecordedError: Recorded Error of the Hip Data. 185 :attr hip_datas: List[HipDataUS]: List of Hip Data. 186 :attr metrics: List[Metric3D]: List of 3D Metrics. 187 :attr graf_frame: int: Frame where the Graf angle is calculated. 188 :attr grafs_hip: HipDataUS: Hip Data where the Graf angle is calculated. 189 :attr dev_metrics: DevMetricsUS: Development Metrics of the Hip Data. 190 :attr video_clip: ImageSequenceClip: Video Clip of the Hip Data. 191 :attr visual_3d: Figure: 3D Visualization of the Hip Data. 192 :attr nifti: NIFTI: NIFTI object of the Hip Data. 193 :attr cr_points: List[float]: List of critical points detected. 194 """ 195 196 def __init__( 197 self, 198 ): 199 self.recorded_error: RecordedError = RecordedError() 200 201 self.hip_datas: List[HipDataUS] = [] 202 203 self.metrics: List[Metric3D] = [] 204 205 self.graf_frame: int = None 206 self.grafs_hip: HipDataUS = None 207 self.dev_metrics: DevMetricsUS = None 208 self.video_clip: ImageSequenceClip = None 209 self.visual_3d: Figure = None 210 self.nifti: NIFTI = None 211 self.cr_points: List[float] = [] 212 213 def __iter__(self) -> HipDataUS: 214 return iter(self.hip_datas) 215 216 def __getitem__(self, index) -> HipDataUS: 217 return self.hip_datas[index] 218 219 def __setitem__(self, index, value): 220 self.hip_datas[index] = value 221 222 def __len__(self): 223 return len(self.hip_datas) 224 225 def __str__(self): 226 output = "" 227 for hip_data in self.hip_datas: 228 output += f"{hip_data}\n" 229 230 return output 231 232 def append(self, hip_data: HipDataUS): 233 """ 234 Append a HipDataUS object to the HipDatasUS object. 235 """ 236 self.hip_datas.append(hip_data) 237 238 def sorted_metrics(self) -> List[Metric3D]: 239 """ 240 Returns the metrics sorted by name. 241 """ 242 return sorted(self.metrics, key=lambda metric: metric.name) 243 244 def json_dump(self, config: Config) -> Dict[str, Union[dict, str]]: 245 """ 246 Returns a dictionary of the Hip Datas in JSON format. 247 248 Used for saving the Hip Datas to a JSON file or returning it from an API call. 249 250 :param config: Config object. 251 252 :return: Dictionary of the Hip Datas in JSON format. 253 """ 254 return { 255 "metrics": [ 256 {metric.dump()[0]: metric.dump()[1:]} 257 for metric in self.metrics 258 ], 259 "graf_frame": self.graf_frame, 260 "dev_metrics": ( 261 self.dev_metrics.json_dump() if self.dev_metrics else None 262 ), 263 "recorded_error": str(self.recorded_error), 264 "keyphrase": config.name, 265 }
Class to store the Hip Data of multiple Hip Images.
:attr recorded_error: RecordedError: Recorded Error of the Hip Data. :attr hip_datas: List[HipDataUS]: List of Hip Data. :attr metrics: List[Metric3D]: List of 3D Metrics. :attr graf_frame: int: Frame where the Graf angle is calculated. :attr grafs_hip: HipDataUS: Hip Data where the Graf angle is calculated. :attr dev_metrics: DevMetricsUS: Development Metrics of the Hip Data. :attr video_clip: ImageSequenceClip: Video Clip of the Hip Data. :attr visual_3d: Figure: 3D Visualization of the Hip Data. :attr nifti: NIFTI: NIFTI object of the Hip Data. :attr cr_points: List[float]: List of critical points detected.
232 def append(self, hip_data: HipDataUS): 233 """ 234 Append a HipDataUS object to the HipDatasUS object. 235 """ 236 self.hip_datas.append(hip_data)
Append a HipDataUS object to the HipDatasUS object.
238 def sorted_metrics(self) -> List[Metric3D]: 239 """ 240 Returns the metrics sorted by name. 241 """ 242 return sorted(self.metrics, key=lambda metric: metric.name)
Returns the metrics sorted by name.
244 def json_dump(self, config: Config) -> Dict[str, Union[dict, str]]: 245 """ 246 Returns a dictionary of the Hip Datas in JSON format. 247 248 Used for saving the Hip Datas to a JSON file or returning it from an API call. 249 250 :param config: Config object. 251 252 :return: Dictionary of the Hip Datas in JSON format. 253 """ 254 return { 255 "metrics": [ 256 {metric.dump()[0]: metric.dump()[1:]} 257 for metric in self.metrics 258 ], 259 "graf_frame": self.graf_frame, 260 "dev_metrics": ( 261 self.dev_metrics.json_dump() if self.dev_metrics else None 262 ), 263 "recorded_error": str(self.recorded_error), 264 "keyphrase": config.name, 265 }
Returns a dictionary of the Hip Datas in JSON format.
Used for saving the Hip Datas to a JSON file or returning it from an API call.
Parameters
- config: Config object.
Returns
Dictionary of the Hip Datas in JSON format.