Coretex
local_image_sample.py
1 # Copyright (C) 2023 Coretex LLC
2 
3 # This file is part of Coretex.ai
4 
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License as
7 # published by the Free Software Foundation, either version 3 of the
8 # License, or (at your option) any later version.
9 
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Affero General Public License for more details.
14 
15 # You should have received a copy of the GNU Affero General Public License
16 # along with this program. If not, see <https://www.gnu.org/licenses/>.
17 
18 from typing import Dict, Any
19 from pathlib import Path
20 
21 import json
22 
23 from .image_sample_data import AnnotatedImageSampleData
24 from .image_format import ImageFormat
25 from ..local_sample import LocalSample
26 from ...annotation import CoretexImageAnnotation
27 
28 
29 class LocalImageSample(LocalSample[AnnotatedImageSampleData]):
30 
31  """
32  Represents the local Image Sample object\n
33  Contains basic properties and functionality for local image Sample classes\n
34  The class has several methods that allow users to access and
35  manipulate local image data and annotations
36  """
37 
38  @property
39  def imagePath(self) -> Path:
40  for format in ImageFormat:
41  imagePaths = list(self.pathpathpath.glob(f"*.{format.extension}"))
42  imagePaths = [path for path in imagePaths if not "thumbnail" in str(path)]
43 
44  if len(imagePaths) > 0:
45  return Path(imagePaths[0])
46 
47  raise FileNotFoundError
48 
49  @property
50  def annotationPath(self) -> Path:
51  return self.pathpathpath / "annotations.json"
52 
53  @property
54  def metadataPath(self) -> Path:
55  return self.pathpathpath / "metadata.json"
56 
57  def load(self) -> AnnotatedImageSampleData:
58  """
59  Loads image and its annotation if it exists
60 
61  Returns
62  -------
63  AnnotatedImageSampleData -> image data and annotation in Coretex.ai format
64  """
65 
66  return AnnotatedImageSampleData(self.pathpathpath)
67 
68  def loadMetadata(self) -> Dict[str, Any]:
69  """
70  Loads sample metadata into a dictionary
71 
72  Returns
73  -------
74  dict[str, Any] -> the metadata as a dict object
75 
76  Raises
77  ------
78  FileNotFoundError -> if metadata file is missing\n
79  ValueError -> if json in the metadata file is list
80  """
81 
82  if not self.metadataPathmetadataPath.exists():
83  raise FileNotFoundError(f"Metadata file \"{self.metadataPath}\" not found")
84 
85  with self.metadataPathmetadataPath.open("r", encoding = "utf-8") as metadataFile:
86  metadata = json.load(metadataFile)
87  if not isinstance(metadata, dict):
88  raise ValueError(f"Metatada for sample \"{self.name}\" is a list. Expected dictionary")
89 
90  return metadata
91 
92  def saveAnnotation(self, coretexAnnotation: CoretexImageAnnotation) -> bool:
93  """
94  Updates annotation for the image
95 
96  Returns
97  -------
98  bool -> returns True if successful, False otherwise
99  """
100 
101  with self.annotationPathannotationPath.open("w") as file:
102  json.dump(coretexAnnotation.encode(), file)
103 
104  self._updateArchive_updateArchive()
105  return True
106 
107  def saveMetadata(self, metadata: Dict[str, Any]) -> None:
108  """
109  Saves a json object as metadata for the sample
110 
111  Parameters
112  ----------
113  metadata : dict[str, Any]
114  Json object containing sample metadata
115  """
116 
117  with self.metadataPathmetadataPath.open("w") as file:
118  json.dump(metadata, file)
119 
120  self._updateArchive_updateArchive()
bool saveAnnotation(self, CoretexImageAnnotation coretexAnnotation)