Spaces:
Running
Running
File size: 9,700 Bytes
55d18b1 8f958ed 55d18b1 8f958ed 55d18b1 8f958ed 55d18b1 8f958ed 55d18b1 8f958ed 55d18b1 8f958ed 5016509 55d18b1 8f958ed 55d18b1 895e8d8 8f958ed 55d18b1 8f958ed 5016509 ba36d57 895e8d8 5016509 895e8d8 ba36d57 895e8d8 5016509 8f958ed 5016509 8f958ed 895e8d8 5016509 55d18b1 5016509 8f958ed 5016509 55d18b1 5016509 8f958ed 5016509 55d18b1 5016509 80c0010 5016509 80c0010 8f958ed 80c0010 5016509 80c0010 8f958ed 80c0010 5016509 80c0010 55d18b1 8f958ed 5016509 8f958ed 55d18b1 8f958ed 55d18b1 5016509 8f958ed 5016509 55d18b1 5016509 8f958ed 5016509 55d18b1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
import hashlib
from input.input_validator import generate_random_md5
# autogenerated class to hold the input data
class InputObservation:
"""
A class to hold an input observation and associated metadata
Attributes:
image (ndarray):
The image associated with the observation.
latitude (float):
The latitude where the observation was made.
longitude (float):
The longitude where the observation was made.
author_email (str):
The email of the author of the observation.
date (Any): # FIXME: specify the type
The date when the observation was made.
time (Any): # FIXME: specify the type
The time when the observation was made.
date_option (datetime.date):
Additional date option for the observation.
time_option (datetime.time):
Additional time option for the observation.
uploaded_file (UploadedFile):
The uploaded file associated with the observation.
image_md5 (str):
The MD5 hash of the image associated with the observation.
Methods:
__str__():
Returns a string representation of the observation.
__repr__():
Returns a string representation of the observation.
__eq__(other):
Checks if two observations are equal.
__ne__(other):
Checks if two observations are not equal.
show_diff(other):
Shows the differences between two observations.
to_dict():
Converts the observation to a dictionary.
from_dict(data):
Creates an observation from a dictionary.
from_input(input):
Creates an observation from another input observation.
"""
_inst_count = 0
def __init__(
self, image:ndarray=None, latitude:float=None, longitude:float=None,
author_email:str=None, date=None, time=None, date_option:datetime.date=None,
time_option:datetime.time=None,
uploaded_file:UploadedFile=None, image_md5:str=None):
self.image = image
self.latitude = latitude
self.longitude = longitude
self.author_email = author_email
self.date = date
self.time = time
self.date_option = date_option
self.time_option = time_option
self.uploaded_file = uploaded_file
self.image_md5 = image_md5
self._top_predictions = []
InputObservation._inst_count += 1
self._inst_id = InputObservation._inst_count
#self.assign_image_md5()
def set_top_predictions(self, top_predictions:list):
self._top_predictions = top_predictions
# add a method to get the top predictions (property?)
@property
def top_predictions(self):
return self._top_predictions
# add a method to assign the image_md5 only once
def assign_image_md5(self):
raise DeprecationWarning("This method is deprecated. hash is a required constructor argument.")
if not self.image_md5:
self.image_md5 = hashlib.md5(self.uploaded_file.read()).hexdigest() if self.uploaded_file else generate_random_md5()
# new comment / hybj hunk
self._cprint(f"[D] Assigned image md5: {self.image_md5} for {self.uploaded_file}")
def _cprint(self, msg:str, color:str=OKGREEN):
"""Print colored message"""
print(f"{color}{msg}{ENDC}")
def __str__(self):
_im_str = "None" if self.image is None else f"image dims: {self.image.shape}"
return (
f"Observation: {_im_str}, {self.latitude}, {self.longitude}, "
f"{self.author_email}, {self.date}, {self.time}, {self.date_option}, "
f"{self.time_option}, {self.uploaded_file}, {self.image_md5}"
)
def __repr__(self):
_im_str = "None" if self.image is None else f"image dims: {self.image.shape}"
return (
f"Observation: "
f"Image: {_im_str}, "
f"Latitude: {self.latitude}, "
f"Longitude: {self.longitude}, "
f"Author Email: {self.author_email}, "
f"Date: {self.date}, "
f"Time: {self.time}, "
f"Date Option: {self.date_option}, "
f"Time Option: {self.time_option}, "
f"Uploaded Filename: {self.uploaded_file}"
f"Image MD5 hash: {self.image_md5}"
)
def __eq__(self, other):
# TODO: ensure this covers all the attributes (some have been added?)
# - except inst_id which is unique
_image_equality = False
if self.image is None or other.image is None:
_image_equality = other.image == self.image
else: # maybe strong assumption: both are correctly ndarray.. should I test types intead?
_image_equality = (self.image == other.image).all()
equality = (
#self.image == other.image and
_image_equality and
self.latitude == other.latitude and
self.longitude == other.longitude and
self.author_email == other.author_email and
self.date == other.date and self.time == other.time and
self.date_option == other.date_option and
# temporarily skip time_option, it is followed by the clock and that is always differnt
#self.time_option == other.time_option and
self.uploaded_file == other.uploaded_file and
self.image_md5 == other.image_md5
)
return equality
# define a function show_diff(other) that shows the differences between two observations
# only highlight the differences, if element is the same don't show it
# have a summary at the top that shows if the observations are the same or not
def show_diff(self, other):
"""Show the differences between two observations"""
differences = []
if self.image is None or other.image is None:
if other.image != self.image:
differences.append(f" Image is different. (types mismatch: {type(self.image)} vs {type(other.image)})")
else:
if (self.image != other.image).any():
cnt = (self.image != other.image).sum()
differences.append(f" Image is different: {cnt} different pixels.")
if self.latitude != other.latitude:
differences.append(f" Latitude is different. (self: {self.latitude}, other: {other.latitude})")
if self.longitude != other.longitude:
differences.append(f" Longitude is different. (self: {self.longitude}, other: {other.longitude})")
if self.author_email != other.author_email:
differences.append(f" Author email is different. (self: {self.author_email}, other: {other.author_email})")
if self.date != other.date:
differences.append(f" Date is different. (self: {self.date}, other: {other.date})")
if self.time != other.time:
differences.append(f" Time is different. (self: {self.time}, other: {other.time})")
if self.date_option != other.date_option:
differences.append(f" Date option is different. (self: {self.date_option}, other: {other.date_option})")
if self.time_option != other.time_option:
differences.append(f" Time option is different. (self: {self.time_option}, other: {other.time_option})")
if self.uploaded_file != other.uploaded_file:
differences.append(" Uploaded filename is different.")
if self.image_md5 != other.image_md5:
differences.append(" Image MD5 hash is different.")
if differences:
print(f"Observations have {len(differences)} differences:")
for diff in differences:
print(diff)
else:
print("Observations are the same.")
def __ne__(self, other):
return not self.__eq__(other)
def to_dict(self):
return {
#"image": self.image,
"image_filename": self.uploaded_file.name if self.uploaded_file else None,
"image_md5": self.image_md5,
#"image_md5": hashlib.md5(self.uploaded_file.read()).hexdigest() if self.uploaded_file else generate_random_md5(),
"latitude": self.latitude,
"longitude": self.longitude,
"author_email": self.author_email,
"date": self.date,
"time": self.time,
"date_option": str(self.date_option),
"time_option": str(self.time_option),
"uploaded_file": self.uploaded_file
}
@classmethod
def from_dict(cls, data):
return cls(
image=data.get("image"),
latitude=data.get("latitude"),
longitude=data.get("longitude"),
author_email=data.get("author_email"),
date=data.get("date"),
time=data.get("time"),
date_option=data.get("date_option"),
time_option=data.get("time_option"),
uploaded_file=data.get("uploaded_file"),
image_hash=data.get("image_md5")
)
@classmethod
def from_input(cls, input):
return cls(
image=input.image,
latitude=input.latitude,
longitude=input.longitude,
author_email=input.author_email,
date=input.date,
time=input.time,
date_option=input.date_option,
time_option=input.time_option,
uploaded_file=input.uploaded_file,
image_hash=input.image_hash
)
|