# Buggy code
def parse_exif_values(self, _path_file):
    # Disable exifread log
    logging.getLogger("exifread").setLevel(logging.CRITICAL)

    with open(_path_file, "rb") as f:
        tags = exifread.process_file(f, details=False)
        try:
            if "Image Make" in tags:
                try:
                    self.camera_make = tags["Image Make"].values
                except UnicodeDecodeError:
                    log.ODM_WARNING("EXIF Image Make might be corrupted")
                    self.camera_make = "unknown"
            if "Image Model" in tags:
                try:
                    self.camera_model = tags["Image Model"].values
                except UnicodeDecodeError:
                    log.ODM_WARNING("EXIF Image Model might be corrupted")
                    self.camera_model = "unknown"
            if "GPS GPSAltitude" in tags:
                self.altitude = self.float_value(tags["GPS GPSAltitude"])
                if (
                    "GPS GPSAltitudeRef" in tags
                    and self.int_value(tags["GPS GPSAltitudeRef"]) > 0
                ):
                    self.altitude *= -1
            if "GPS GPSLatitude" in tags and "GPS GPSLatitudeRef" in tags:
                self.latitude = self.dms_to_decimal(
                    tags["GPS GPSLatitude"], tags["GPS GPSLatitudeRef"]
                )
            if "GPS GPSLongitude" in tags and "GPS GPSLongitudeRef" in tags:
                self.longitude = self.dms_to_decimal(
                    tags["GPS GPSLongitude"], tags["GPS GPSLongitudeRef"]
                )
        except IndexError as e:
            log.ODM_WARNING(
                "Cannot read basic EXIF tags for %s: %s" % (_path_file, e.message)
            )

        try:
            if "Image Tag 0xC61A" in tags:
                self.black_level = self.list_values(tags["Image Tag 0xC61A"])
            elif "BlackLevel" in tags:
                self.black_level = self.list_values(tags["BlackLevel"])

            if "EXIF ExposureTime" in tags:
                self.exposure_time = self.float_value(tags["EXIF ExposureTime"])

            if "EXIF FNumber" in tags:
                self.fnumber = self.float_value(tags["EXIF FNumber"])

            if "EXIF ISOSpeed" in tags:
                self.iso_speed = self.int_value(tags["EXIF ISOSpeed"])
            elif "EXIF PhotographicSensitivity" in tags:
                self.iso_speed = self.int_value(tags["EXIF PhotographicSensitivity"])
            elif "EXIF ISOSpeedRatings" in tags:
                self.iso_speed = self.int_value(tags["EXIF ISOSpeedRatings"])

            if "Image BitsPerSample" in tags:
                self.bits_per_sample = self.int_value(tags["Image BitsPerSample"])
            if "EXIF DateTimeOriginal" in tags:
                str_time = tags["EXIF DateTimeOriginal"].values
                utc_time = datetime.strptime(str_time, "%Y:%m:%d %H:%M:%S")
                subsec = 0
                if "EXIF SubSecTime" in tags:
                    subsec = self.int_value(tags["EXIF SubSecTime"])
                negative = 1.0
                if subsec < 0:
                    negative = -1.0
                    subsec *= -1.0
                subsec = float("0.{}".format(int(subsec)))
                subsec *= negative
                ms = subsec * 1e3
                utc_time += timedelta(milliseconds=ms)
                timezone = pytz.timezone("UTC")
                epoch = timezone.localize(datetime.utcfromtimestamp(0))
                self.utc_time = (
                    timezone.localize(utc_time) - epoch
                ).total_seconds() * 1000.0
        except Exception as e:
            log.ODM_WARNING(
                "Cannot read extended EXIF tags for %s: %s" % (_path_file, str(e))
            )

        # Extract XMP tags
        f.seek(0)
        xmp = self.get_xmp(f)

        for tags in xmp:
            try:
                band_name = self.get_xmp_tag(
                    tags, ["Camera:BandName", "@Camera:BandName"]
                )
                if band_name is not None:
                    self.band_name = band_name.replace(" ", "")

                self.set_attr_from_xmp_tag(
                    "band_index",
                    tags,
                    [
                        "DLS:SensorId",  # Micasense RedEdge
                        "@Camera:RigCameraIndex",  # Parrot Sequoia, Sentera 21244-00_3.2MP-GS-0001
                        "Camera:RigCameraIndex",  # MicaSense Altum
                    ],
                )
                self.set_attr_from_xmp_tag(
                    "radiometric_calibration",
                    tags,
                    [
                        "MicaSense:RadiometricCalibration",
                    ],
                )

                self.set_attr_from_xmp_tag(
                    "vignetting_center",
                    tags,
                    [
                        "Camera:VignettingCenter",
                        "Sentera:VignettingCenter",
                    ],
                )

                self.set_attr_from_xmp_tag(
                    "vignetting_polynomial",
                    tags,
                    [
                        "Camera:VignettingPolynomial",
                        "Sentera:VignettingPolynomial",
                    ],
                )

                self.set_attr_from_xmp_tag(
                    "horizontal_irradiance",
                    tags,
                    ["Camera:HorizontalIrradiance"],
                    float,
                )

                self.set_attr_from_xmp_tag(
                    "irradiance_scale_to_si",
                    tags,
                    ["Camera:IrradianceScaleToSIUnits"],
                    float,
                )

                self.set_attr_from_xmp_tag(
                    "sun_sensor",
                    tags,
                    [
                        "Camera:SunSensor",
                    ],
                    float,
                )

                self.set_attr_from_xmp_tag(
                    "spectral_irradiance",
                    tags,
                    [
                        "Camera:SpectralIrradiance",
                        "Camera:Irradiance",
                    ],
                    float,
                )

                # Phantom 4 RTK
                if "@drone-dji:RtkStdLon" in tags:
                    y = float(self.get_xmp_tag(tags, "@drone-dji:RtkStdLon"))
                    x = float(self.get_xmp_tag(tags, "@drone-dji:RtkStdLat"))
                    self.gps_xy_stddev = max(x, y)

                    if "@drone-dji:RtkStdHgt" in tags:
                        self.gps_z_stddev = float(
                            self.get_xmp_tag(tags, "@drone-dji:RtkStdHgt")
                        )
                else:
                    self.set_attr_from_xmp_tag(
                        "gps_xy_stddev",
                        tags,
                        ["@Camera:GPSXYAccuracy", "GPSXYAccuracy"],
                        float,
                    )
                    self.set_attr_from_xmp_tag(
                        "gps_z_stddev",
                        tags,
                        ["@Camera:GPSZAccuracy", "GPSZAccuracy"],
                        float,
                    )

                if "DLS:Yaw" in tags:
                    self.set_attr_from_xmp_tag("dls_yaw", tags, ["DLS:Yaw"], float)
                    self.set_attr_from_xmp_tag("dls_pitch", tags, ["DLS:Pitch"], float)
                    self.set_attr_from_xmp_tag("dls_roll", tags, ["DLS:Roll"], float)
            except Exception as e:
                log.ODM_WARNING(
                    "Cannot read XMP tags for %s: %s" % (_path_file, e.message)
                )

            # self.set_attr_from_xmp_tag('center_wavelength', tags, [
            #     'Camera:CentralWavelength'
            # ], float)

            # self.set_attr_from_xmp_tag('bandwidth', tags, [
            #     'Camera:WavelengthFWHM'
            # ], float)

    self.width, self.height = get_image_size.get_image_size(_path_file)
    # Sanitize band name since we use it in folder paths
    self.band_name = re.sub("[^A-Za-z0-9]+", "", self.band_name)


# Traceback (ValueError)
[INFO]    Loading 4 images
Traceback (most recent call last):
File "/code/opendm/photo.py", line 225, in parse_exif_values
], float)
File "/code/opendm/photo.py", line 256, in set_attr_from_xmp_tag
setattr(self, attr, cast(v))
ValueError: could not convert string to float: '610/1000'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/code/run.py", line 68, in <module>
app.execute()
File "/code/stages/odm_app.py", line 95, in execute
self.first_stage.run()
File "/code/opendm/types.py", line 337, in run
self.process(self.args, outputs)
File "/code/stages/dataset.py", line 109, in process
p = types.ODM_Photo(f)
File "/code/opendm/photo.py", line 70, in __init__
self.parse_exif_values(path_file)
File "/code/opendm/photo.py", line 236, in parse_exif_values
log.ODM_WARNING("Cannot read XMP tags for %s: %s" % (_path_file, e.message))
AttributeError: 'ValueError' object has no attribute 'message'

# Fixed code
def parse_exif_values(self, _path_file):
    # Disable exifread log
    logging.getLogger("exifread").setLevel(logging.CRITICAL)

    with open(_path_file, "rb") as f:
        tags = exifread.process_file(f, details=False)
        try:
            if "Image Make" in tags:
                try:
                    self.camera_make = tags["Image Make"].values
                except UnicodeDecodeError:
                    log.ODM_WARNING("EXIF Image Make might be corrupted")
                    self.camera_make = "unknown"
            if "Image Model" in tags:
                try:
                    self.camera_model = tags["Image Model"].values
                except UnicodeDecodeError:
                    log.ODM_WARNING("EXIF Image Model might be corrupted")
                    self.camera_model = "unknown"
            if "GPS GPSAltitude" in tags:
                self.altitude = self.float_value(tags["GPS GPSAltitude"])
                if (
                    "GPS GPSAltitudeRef" in tags
                    and self.int_value(tags["GPS GPSAltitudeRef"]) > 0
                ):
                    self.altitude *= -1
            if "GPS GPSLatitude" in tags and "GPS GPSLatitudeRef" in tags:
                self.latitude = self.dms_to_decimal(
                    tags["GPS GPSLatitude"], tags["GPS GPSLatitudeRef"]
                )
            if "GPS GPSLongitude" in tags and "GPS GPSLongitudeRef" in tags:
                self.longitude = self.dms_to_decimal(
                    tags["GPS GPSLongitude"], tags["GPS GPSLongitudeRef"]
                )
        except IndexError as e:
            log.ODM_WARNING(
                "Cannot read basic EXIF tags for %s: %s" % (_path_file, str(e))
            )

        try:
            if "Image Tag 0xC61A" in tags:
                self.black_level = self.list_values(tags["Image Tag 0xC61A"])
            elif "BlackLevel" in tags:
                self.black_level = self.list_values(tags["BlackLevel"])

            if "EXIF ExposureTime" in tags:
                self.exposure_time = self.float_value(tags["EXIF ExposureTime"])

            if "EXIF FNumber" in tags:
                self.fnumber = self.float_value(tags["EXIF FNumber"])

            if "EXIF ISOSpeed" in tags:
                self.iso_speed = self.int_value(tags["EXIF ISOSpeed"])
            elif "EXIF PhotographicSensitivity" in tags:
                self.iso_speed = self.int_value(tags["EXIF PhotographicSensitivity"])
            elif "EXIF ISOSpeedRatings" in tags:
                self.iso_speed = self.int_value(tags["EXIF ISOSpeedRatings"])

            if "Image BitsPerSample" in tags:
                self.bits_per_sample = self.int_value(tags["Image BitsPerSample"])
            if "EXIF DateTimeOriginal" in tags:
                str_time = tags["EXIF DateTimeOriginal"].values
                utc_time = datetime.strptime(str_time, "%Y:%m:%d %H:%M:%S")
                subsec = 0
                if "EXIF SubSecTime" in tags:
                    subsec = self.int_value(tags["EXIF SubSecTime"])
                negative = 1.0
                if subsec < 0:
                    negative = -1.0
                    subsec *= -1.0
                subsec = float("0.{}".format(int(subsec)))
                subsec *= negative
                ms = subsec * 1e3
                utc_time += timedelta(milliseconds=ms)
                timezone = pytz.timezone("UTC")
                epoch = timezone.localize(datetime.utcfromtimestamp(0))
                self.utc_time = (
                    timezone.localize(utc_time) - epoch
                ).total_seconds() * 1000.0
        except Exception as e:
            log.ODM_WARNING(
                "Cannot read extended EXIF tags for %s: %s" % (_path_file, str(e))
            )

        # Extract XMP tags
        f.seek(0)
        xmp = self.get_xmp(f)

        for tags in xmp:
            try:
                band_name = self.get_xmp_tag(
                    tags, ["Camera:BandName", "@Camera:BandName"]
                )
                if band_name is not None:
                    self.band_name = band_name.replace(" ", "")

                self.set_attr_from_xmp_tag(
                    "band_index",
                    tags,
                    [
                        "DLS:SensorId",  # Micasense RedEdge
                        "@Camera:RigCameraIndex",  # Parrot Sequoia, Sentera 21244-00_3.2MP-GS-0001
                        "Camera:RigCameraIndex",  # MicaSense Altum
                    ],
                )
                self.set_attr_from_xmp_tag(
                    "radiometric_calibration",
                    tags,
                    [
                        "MicaSense:RadiometricCalibration",
                    ],
                )

                self.set_attr_from_xmp_tag(
                    "vignetting_center",
                    tags,
                    [
                        "Camera:VignettingCenter",
                        "Sentera:VignettingCenter",
                    ],
                )

                self.set_attr_from_xmp_tag(
                    "vignetting_polynomial",
                    tags,
                    [
                        "Camera:VignettingPolynomial",
                        "Sentera:VignettingPolynomial",
                    ],
                )

                self.set_attr_from_xmp_tag(
                    "horizontal_irradiance",
                    tags,
                    ["Camera:HorizontalIrradiance"],
                    float,
                )

                self.set_attr_from_xmp_tag(
                    "irradiance_scale_to_si",
                    tags,
                    ["Camera:IrradianceScaleToSIUnits"],
                    float,
                )

                self.set_attr_from_xmp_tag(
                    "sun_sensor",
                    tags,
                    [
                        "Camera:SunSensor",
                    ],
                    float,
                )

                self.set_attr_from_xmp_tag(
                    "spectral_irradiance",
                    tags,
                    [
                        "Camera:SpectralIrradiance",
                        "Camera:Irradiance",
                    ],
                    float,
                )

                # Phantom 4 RTK
                if "@drone-dji:RtkStdLon" in tags:
                    y = float(self.get_xmp_tag(tags, "@drone-dji:RtkStdLon"))
                    x = float(self.get_xmp_tag(tags, "@drone-dji:RtkStdLat"))
                    self.gps_xy_stddev = max(x, y)

                    if "@drone-dji:RtkStdHgt" in tags:
                        self.gps_z_stddev = float(
                            self.get_xmp_tag(tags, "@drone-dji:RtkStdHgt")
                        )
                else:
                    self.set_attr_from_xmp_tag(
                        "gps_xy_stddev",
                        tags,
                        ["@Camera:GPSXYAccuracy", "GPSXYAccuracy"],
                        float,
                    )
                    self.set_attr_from_xmp_tag(
                        "gps_z_stddev",
                        tags,
                        ["@Camera:GPSZAccuracy", "GPSZAccuracy"],
                        float,
                    )

                if "DLS:Yaw" in tags:
                    self.set_attr_from_xmp_tag("dls_yaw", tags, ["DLS:Yaw"], float)
                    self.set_attr_from_xmp_tag("dls_pitch", tags, ["DLS:Pitch"], float)
                    self.set_attr_from_xmp_tag("dls_roll", tags, ["DLS:Roll"], float)
            except Exception as e:
                log.ODM_WARNING(
                    "Cannot read XMP tags for %s: %s" % (_path_file, str(e))
                )

            # self.set_attr_from_xmp_tag('center_wavelength', tags, [
            #     'Camera:CentralWavelength'
            # ], float)

            # self.set_attr_from_xmp_tag('bandwidth', tags, [
            #     'Camera:WavelengthFWHM'
            # ], float)

    self.width, self.height = get_image_size.get_image_size(_path_file)
    # Sanitize band name since we use it in folder paths
    self.band_name = re.sub("[^A-Za-z0-9]+", "", self.band_name)