#!/usr/bin/env python3
# =========================================================================
# Program: iota2
#
# Copyright (c) CESBIO. All rights reserved.
#
# See LICENSE for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even
# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the above copyright notices for more information.
#
# =========================================================================
"""Module defining different exception classes for iota2"""
from pathlib import Path
from iota2.common import i2_constants
I2_CONST = i2_constants.Iota2Constants()
[docs]class I2error(Exception):
"""Base class for exceptions in iota2 chain"""
[docs] def __init__(self, msg: str):
self.msg = msg
[docs]class TooManyColumnsError(I2error):
"""Exceptions thrown when the number of columns inside the learning samples
file is too high."""
[docs] def __init__(self) -> None:
msg = (
f"ERROR too many features (>{I2_CONST.sqlite_max_column}) to generate "
"sqlite file you should set the configuration parameter "
"learning_samples_extension (arg_train section) to 'csv'"
)
I2error.__init__(self, msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class FeaturesShapeError(I2error):
"""Raise if output features are not 2D or 3D"""
[docs] def __init__(self, shape: tuple[int, ...]):
msg = f"output feature's must be a 2D or 3D shape, found {len(shape)}D"
I2error.__init__(self, msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class NeuralNetworkConstructorError(I2error):
"""
Raise if NN constructor arguments not the expected ones.
Parameters
----------
expected_args:
Expected arguments
current_args:
Current (wrong) arguments
"""
[docs] def __init__(self, expected_args: list[str], current_args: list[str]):
msg = (
f"Neural network constructor arguments must be : {' '.join(expected_args)}"
f" not {' '.join(current_args)}"
)
I2error.__init__(self, msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class DirectoryError(I2error):
"""Base subclass for exception in the configuration file
IN :
msg [string] : explanation of the error
"""
[docs] def __init__(self, directory_path: Path | str):
msg = f"directory : {directory_path} cannot be created"
I2error.__init__(self, msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class IntersectionError(I2error):
"""Base subclass for exception in the configuration file
IN :
msg [string] : explanation of the error
"""
[docs] def __init__(self) -> None:
msg = "no intersection between georeferenced inputs"
I2error.__init__(self, msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class ConfigFileError(I2error):
"""Base subclass for exception in the configuration file
IN :
msg [string] : explanation of the error
"""
[docs] def __init__(self, msg: str):
I2error.__init__(self, msg)
self.msg = msg
def __str__(self) -> str:
return repr(f"iota2 ERROR : {self.msg}")
[docs]class DataBaseError(I2error):
"""Base subclass for exception in a database (SQLITE, shapefile)"""
[docs] def __init__(self, msg: str):
I2error.__init__(self, msg)
self.msg = msg
def __str__(self) -> str:
return repr(f"dataBaseError : {self.msg}")
[docs]class SqliteCorrupted(DataBaseError):
"""Raise if an SQLITE file is corrupted"""
[docs] def __init__(self, journalsqlite_path: str):
sqlite_path = journalsqlite_path.replace("-journal", "")
msg = (
f"'.sqlite-journal' file detected, please remove "
f"{journalsqlite_path} and {sqlite_path}"
)
super().__init__(msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class InvalidGeometry(DataBaseError):
"""Raise if a geometry in a shapefile is invalid"""
[docs] def __init__(self, msg: str):
super().__init__(msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class InvalidProjection(DataBaseError):
"""Raise if the provided projection isn't valid (None, not the expected one ...)"""
[docs] def __init__(self, msg: str):
super().__init__(msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class EmptyFeatures(DataBaseError):
"""Raise if a shapefile contains empty features"""
[docs] def __init__(self, msg: str):
super().__init__(msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class EmptyGeometry(DataBaseError):
"""Raise if a shapefile contains empty geometries"""
[docs] def __init__(self, msg: str):
super().__init__(msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class DuplicatedFeatures(DataBaseError):
"""Raise if a shapefile contains duplicated features"""
[docs] def __init__(self, msg: str):
super().__init__(msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class ContainsMultipolygon(DataBaseError):
"""Raise if a shapefile contains at least one multipolygon"""
[docs] def __init__(self, msg: str):
super().__init__(msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class NamingConvention(DataBaseError):
"""Raise if a file's name doesn't follow a specific convention"""
[docs] def __init__(self, msg: str):
super().__init__(msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class MissingField(DataBaseError):
"""
Raise if a field is missing in a shapefile
Parameters
----------
database_path:
Database path
missing_field:
Missing field
"""
[docs] def __init__(self, database_path: Path | str, missing_field: str):
msg = f"{database_path} does not contains the field '{missing_field}'"
super().__init__(msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class FieldType(DataBaseError):
"""
Raise if a shapefile's field is of the wrong type.
Parameters
----------
input_vector:
Shapefile path
data_field
Current field type
expected_type:
Expected field type
"""
[docs] def __init__(self, input_vector: Path | str, data_field: str, expected_type: type):
msg = f"the field '{data_field}' in {input_vector} must be {expected_type} type"
super().__init__(msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class TooSmallRegion(DataBaseError):
"""Raise if some regions are too small
Parameters
----------
input_vector:
Input shapefile
area_threshold:
Fixed threshold for regions' area
nb_too_small_geoms:
Number of regions that are smaller than the threshold
"""
[docs] def __init__(
self,
input_vector: Path | str,
area_threshold: float,
nb_too_small_geoms: int,
):
msg = (
f"the region shape '{input_vector}' contains {nb_too_small_geoms} "
f"regions or sub-regions inferior than {area_threshold}, please remove them."
)
super().__init__(msg)
self.msg = msg
def __str__(self) -> str:
return repr(self.msg)
[docs]class DirError(ConfigFileError):
"""Exception raised for errors in mandatory directory
IN :
directory [string] : name of the directory
"""
[docs] def __init__(self, directory: Path | str):
super().__init__(str(directory))
self.directory = directory
def __str__(self) -> str:
self.msg = "Error: " + repr(self.directory) + " doesn't exist"
return self.msg
[docs]class ConfigError(ConfigFileError):
"""Exception raised for configuration errors in the configuration file
(like incompatible parameters)
IN :
msg [string] : explanation of the error
"""
[docs] def __init__(self, msg: str):
self.msg = msg
super().__init__(msg)
def __str__(self) -> str:
return "Error: " + repr(self.msg)
[docs]class FileError(ConfigFileError):
"""Exception raised for errors inside an input file
(like a bad format or absence of a variable)
IN :
msg [string] : explanation of the error
"""
[docs] def __init__(self, msg: str):
super().__init__(msg)
self.msg = msg
def __str__(self) -> str:
return "Error: " + repr(self.msg)