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        }
class LandmarksUS:
 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

LandmarksUS( left: Tuple[int, int] = None, right: Tuple[int, int] = None, apex: Tuple[int, int] = None, point_D: Tuple[int, int] = None, point_d: Tuple[int, int] = None, mid_cov_point: Tuple[int, int] = None)
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
left
right
apex
point_D
point_d
mid_cov_point
def items(self) -> Dict[str, Tuple]:
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()
def to_dict(self) -> Dict[str, Tuple[int, int]]:
 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.

class HipDataUS:
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.

HipDataUS( landmarks: LandmarksUS = None, metrics: List[retuve.classes.metrics.Metric2D] = None, frame_no: int = None, side: retuve.hip_us.classes.enums.Side = None)
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
landmarks
frame_no
side
metrics
def marked(self) -> bool:
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.

def get_metric(self, name: str) -> float:
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.

def json_dump( self, config: retuve.keyphrases.config.Config, dev_metrics: retuve.hip_us.classes.dev.DevMetricsUS):
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.

class HipDatasUS:
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.

hip_datas: List[HipDataUS]
graf_frame: int
grafs_hip: HipDataUS
video_clip: moviepy.video.io.ImageSequenceClip.ImageSequenceClip
visual_3d: plotly.graph_objs._figure.Figure
nifti: radstract.data.nifti.main.NIFTI
cr_points: List[float]
def append(self, hip_data: HipDataUS):
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.

def sorted_metrics(self) -> List[retuve.classes.metrics.Metric3D]:
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.

def json_dump( self, config: retuve.keyphrases.config.Config) -> Dict[str, Union[dict, str]]:
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.