Skip to content

c_data_type_handler

Classes:

CIntegerDataTypeInfo dataclass

CIntegerDataTypeInfo(
    gdal_data_type_string: str,
    numpy_data_type_string: str,
    bits: int,
    signed: bool,
)

Class to hold information about C integer data types.

MinimumCDataTypeHandler

Methods:

check_if_user_requested_data_type_deviates classmethod

check_if_user_requested_data_type_deviates(
    user_defined_minimum_gdal_type: geokit_c_data_types_literal
    | None,
    automatically_determined_minimum_gdal_type: gdal_c_raster_data_types_literal,
)

Checks if the user defined minimum gdal data type deviates from the automatically determined minimum gdal data type. Raises a warning if the two data types differ.

Parameters:

  • user_defined_minimum_gdal_type

    (geokit_c_data_types_literal | None) –

    The user defined minimum gdal data type.

  • automatically_determined_minimum_gdal_type

    (gdal_c_raster_data_types_literal) –

    The automatically determined minimum gdal data type.

Source code in geokit/c_data_type_handler.py
@classmethod
def check_if_user_requested_data_type_deviates(
    cls,
    user_defined_minimum_gdal_type: geokit_c_data_types_literal | None,
    automatically_determined_minimum_gdal_type: gdal_c_raster_data_types_literal,
):
    """Checks if the user defined minimum gdal data type deviates from the automatically determined minimum gdal data type. Raises a warning if the two data types differ.

    Parameters
    ----------
    user_defined_minimum_gdal_type : geokit_c_data_types_literal | None
        The user defined minimum gdal data type.
    automatically_determined_minimum_gdal_type : gdal_c_raster_data_types_literal
        The automatically determined minimum gdal data type.
    """
    if user_defined_minimum_gdal_type is not None:
        converted_user_defined_minimum_gdal_type_list = cls._convert_abbreviation_to_gdal_data_type(
            input_string_list=[user_defined_minimum_gdal_type]
        )
        converted_user_defined_minimum_gdal_type = converted_user_defined_minimum_gdal_type_list[0]
        if automatically_determined_minimum_gdal_type != converted_user_defined_minimum_gdal_type:
            warning_message = (
                f"The user-defined minimum GDAL data type: {user_defined_minimum_gdal_type},"
                f" which is understood as the rigorous GDAL datatype: {converted_user_defined_minimum_gdal_type},"
                f" differs from automatically determined data type: {automatically_determined_minimum_gdal_type}."
                " To silence this warning check the configuration of your function call for configurations that might cause an unintentional overflow error."
                " Otherwise you can just set the data type to the automatically determined data type or to the Python object None."
            )
            warnings.warn(
                message=warning_message,
                category=UserWarning,
            )

get_gdal_constant_from_string staticmethod

get_gdal_constant_from_string(input_string: str) -> int

This function converts a gdal data type string to the corresponding gdal constant that represents the data type.

Parameters:

  • input_string

    (str) –

    String that should be converted to gdal constant.

Returns:

  • int

    Integer representing the gdal data type. This can be passed to gdal functions that require a data type constant.

Source code in geokit/c_data_type_handler.py
@staticmethod
def get_gdal_constant_from_string(input_string: str) -> int:
    """This function converts a gdal data type string to the corresponding gdal constant that represents the data type.

    Parameters
    ----------
    input_string : str
        String that should be converted to gdal constant.

    Returns
    -------
    int
        Integer representing the gdal data type. This can be passed to gdal functions that require a data type constant.

    """
    if input_string[0:4] == "GDT_":
        constant_string = input_string
    else:
        constant_string = "GDT_" + input_string

    if hasattr(gdal, constant_string):
        gdal_data_type_constant = getattr(gdal, constant_string)
        return gdal_data_type_constant
    else:
        raise ValueError(f"Data type {input_string} is not a valid GDAL data type")

get_valid_gdal_data_type_as_constant classmethod

get_valid_gdal_data_type_as_constant(
    list_of_numbers: list[
        float
        | int
        | integer
        | floating
        | complexfloating
        | bool
        | bool_
    ],
    minimum_gdal_type_list: list[
        geokit_c_data_types_literal
    ]
    | None = None,
    user_defined_minimum_gdal_type: geokit_c_data_types_literal
    | None = None,
) -> int

This Function determines the minimum required data type to store all numbers provided list_of_numbers in the same data type.

Additionally the user can provide a list of minimum required data types that need to be considered as well as a user defined minimum data type. The data types in the gdal_type_list can be provided to get at least the data type provided in the list or a bigger one if needed. The user defined minimum data type is only used to warn the user if the automatically determined data type differs from the user defined one. This is useful identify a potential misconfiguration.

Parameters:

  • list_of_numbers

    (list[float | int | integer | floating | complexfloating | bool | bool_]) –

    A list of numbers for which the minimum required gdal data type should be determined.

  • minimum_gdal_type_list

    (list[geokit_c_data_types_literal] | None, default: None ) –

    This is a list of the minimum required GDAL data types that need to be considered. If a larger data type is required, the input is ignored. If no data types are provided, they are automatically determined from the list of numbers. by default None

  • user_defined_minimum_gdal_type

    (geokit_c_data_types_literal | None, default: None ) –

    The data type that the user expects. If a different data type is determined automatically a warning is raised. If set to None no warning is raised., by default None

Returns:

  • int

    An integer that represents represents a C datatype that must be passed to certain GDAL functions. To convert it to a human readable string use the function get_gdal_constant_from_string or use the get_valid_gdal_data_type_as_string instead of this function.

Source code in geokit/c_data_type_handler.py
@classmethod
def get_valid_gdal_data_type_as_constant(
    cls,
    list_of_numbers: list[float | int | np.integer | np.floating | np.complexfloating | bool | np.bool_],
    minimum_gdal_type_list: list[geokit_c_data_types_literal] | None = None,
    user_defined_minimum_gdal_type: geokit_c_data_types_literal | None = None,
) -> int:
    """This Function determines the minimum required data type to store all numbers provided list_of_numbers in the same data type.

    Additionally the user can provide a list of minimum required data types that need to be considered as well as a user defined minimum data type.
    The data types in the gdal_type_list can be provided to get at least the data type provided in the list or a bigger one if needed.
    The user defined minimum data type is only used to warn the user if the automatically determined data type differs from the user defined one.
    This is useful identify a potential misconfiguration.

    Parameters
    ----------
    list_of_numbers : list[float  |  int  |  np.integer  |  np.floating  |  np.complexfloating  |  bool  |  np.bool_]
        A list of numbers for which the minimum required gdal data type should be determined.
    minimum_gdal_type_list : list[geokit_c_data_types_literal] | None, optional
        This is a list of the minimum required GDAL data types that need to be considered. If a larger data type is required, the input is ignored.
        If no data types are provided, they are automatically determined from the list of numbers. by default None
    user_defined_minimum_gdal_type : geokit_c_data_types_literal | None, optional
        The data type that the user expects. If a different data type is determined automatically a warning is raised. If set to None no warning is raised., by default None

    Returns
    -------
    int
        An integer that represents represents a C datatype that must be passed to certain GDAL functions. To convert it to a human readable string use the function get_gdal_constant_from_string
        or use the get_valid_gdal_data_type_as_string instead of this function.
    """
    data_type_string = cls.get_valid_gdal_data_type_as_string(
        list_of_numbers=list_of_numbers,
        minimum_gdal_type_list=minimum_gdal_type_list,
        user_defined_minimum_gdal_type=user_defined_minimum_gdal_type,
    )
    data_type_constant = cls.get_gdal_constant_from_string(input_string=data_type_string)
    return data_type_constant

get_valid_gdal_data_type_as_string classmethod

get_valid_gdal_data_type_as_string(
    list_of_numbers: list[
        float
        | int
        | integer
        | floating
        | complexfloating
        | bool
        | bool_
    ],
    minimum_gdal_type_list: list[
        geokit_c_data_types_literal
    ]
    | None = None,
    user_defined_minimum_gdal_type: geokit_c_data_types_literal
    | None = None,
) -> str

This Function determines the minimum required data type to store all numbers provided list_of_numbers in the same data type.

Additionally the user can provide a list of minimum required data types that need to be considered as well as a user defined minimum data type. The data types in the gdal_type_list can be provided to get at least the data type provided in the list or a bigger one if needed. The user defined minimum data type is only used to warn the user if the automatically determined data type differs from the user defined one. This is useful identify a potential misconfiguration.

Parameters:

  • list_of_numbers

    (list[float | int | integer | floating | complexfloating | bool | bool_]) –

    A list of numbers for which the minimum required gdal data type should be determined.

  • minimum_gdal_type_list

    (list[geokit_c_data_types_literal] | None, default: None ) –

    This is a list of the minimum required GDAL data types that need to be considered. If a larger data type is required, the input is ignored. If no data types are provided, they are automatically determined from the list of numbers. by default None

  • user_defined_minimum_gdal_type

    (geokit_c_data_types_literal | None, default: None ) –

    The data type that the user expects. If a different data type is determined automatically a warning is raised. If set to None no warning is raised., by default None

Returns:

  • str

    A a string of the number data type that can be used in gdal to store all numbers provided in list_of_numbers.

Source code in geokit/c_data_type_handler.py
@classmethod
def get_valid_gdal_data_type_as_string(
    cls,
    list_of_numbers: list[float | int | np.integer | np.floating | np.complexfloating | bool | np.bool_],
    minimum_gdal_type_list: list[geokit_c_data_types_literal] | None = None,
    user_defined_minimum_gdal_type: geokit_c_data_types_literal | None = None,
) -> str:
    """This Function determines the minimum required data type to store all numbers provided list_of_numbers in the same data type.

    Additionally the user can provide a list of minimum required data types that need to be considered as well as a user defined minimum data type.
    The data types in the gdal_type_list can be provided to get at least the data type provided in the list or a bigger one if needed.
    The user defined minimum data type is only used to warn the user if the automatically determined data type differs from the user defined one.
    This is useful identify a potential misconfiguration.

    Parameters
    ----------
    list_of_numbers : list[float  |  int  |  np.integer  |  np.floating  |  np.complexfloating  |  bool  |  np.bool_]
        A list of numbers for which the minimum required gdal data type should be determined.
    minimum_gdal_type_list : list[geokit_c_data_types_literal] | None, optional
        This is a list of the minimum required GDAL data types that need to be considered. If a larger data type is required, the input is ignored.
        If no data types are provided, they are automatically determined from the list of numbers. by default None
    user_defined_minimum_gdal_type : geokit_c_data_types_literal | None, optional
        The data type that the user expects. If a different data type is determined automatically a warning is raised. If set to None no warning is raised., by default None

    Returns
    -------
    str
        A a string of the number data type that can be used in gdal to store all numbers provided in list_of_numbers.

    """
    minimum_gdal_type_list_converted = cls._convert_abbreviation_to_gdal_data_type(
        input_string_list=minimum_gdal_type_list
    )
    if user_defined_minimum_gdal_type is None:
        user_defined_minimum_gdal_type_converted_list = [None]
    elif isinstance(user_defined_minimum_gdal_type, str):
        user_defined_minimum_gdal_type_converted_list = cls._convert_abbreviation_to_gdal_data_type(
            input_string_list=[user_defined_minimum_gdal_type]
        )
    else:
        raise GeoKitCDataError(
            "For argument: user_defined_minimum_gdal_type either a string with a valid Gdal datatype or None is allowed. However the following type has been provided: {user_defined_minimum_gdal_type}"
        )
    user_defined_minimum_gdal_type_converted = user_defined_minimum_gdal_type_converted_list[0]

    list_of_integer: list[int | np.integer] = []
    list_of_float_data_types: list[np.dtype] = []
    list_of_complex_floats = []
    for current_number in list_of_numbers:
        # if type(current_number) == type(bool):
        if isinstance(current_number, (bool, np.bool_)):
            if isinstance(minimum_gdal_type_list, list):
                minimum_gdal_type_list.append("GDT_Int8")
            else:
                minimum_gdal_type_list = ["GDT_Int8"]
        elif isinstance(current_number, (int, np.integer)):
            list_of_integer.append(current_number)
        elif np.isnan(current_number) or np.isinf(current_number):
            minimum_data_type_float = np.dtype("float16")
            list_of_float_data_types.append(minimum_data_type_float)
        elif isinstance(current_number, float):
            integer_float: int = int(current_number)
            if current_number == integer_float:
                list_of_integer.append(integer_float)
            else:
                list_of_float_data_types.append(np.min_scalar_type(current_number))
        elif isinstance(current_number, np.number):
            if np.issubdtype(current_number, np.floating):
                list_of_float_data_types.append(np.min_scalar_type(current_number))
            elif np.issubdtype(current_number, np.complexfloating):
                list_of_complex_floats.append(current_number)
            else:
                raise GeoKitCDataError(
                    f"GeoKit only supports the integers, floats and complex floats as numpy data types. Nonetheless the following data type has been provided {type(current_number)} "
                )
        else:
            raise GeoKitCDataError(
                f"GeoKit only supports the integers, floats and complex floats as data types. Nonetheless the following data type has been provided {type(current_number)} "
            )
    list_of_output_float_data_types, list_of_output_integers = cls._check_if_integers_can_be_displayed_as_integers(
        list_of_numbers=list_of_integer
    )

    list_of_float_data_types.extend(list_of_output_float_data_types)

    if isinstance(minimum_gdal_type_list_converted, list):
        if minimum_gdal_type_list_converted:
            c_number_category = cls._determine_if_gdal_data_type_is_int_float_or_complex(
                minimum_gdal_type_list_converted
            )
        else:
            c_number_category = None
    elif minimum_gdal_type_list_converted is None:
        c_number_category = None
    else:
        raise GeoKitCDataError(
            "For argument: minimum_gdal_type either a list of strings with valid Gdal datatypes or None is allowed. However the following type has been provided: {minimum_gdal_type}"
        )

    if list_of_complex_floats or c_number_category == "GDT_CInt" or c_number_category == "GDT_CFloat":
        raise GeoKitCDataError("Complex Data Types are not implemented yet.")
    if not list_of_float_data_types and not list_of_output_integers and c_number_category is None:
        cls.check_if_user_requested_data_type_deviates(
            user_defined_minimum_gdal_type=user_defined_minimum_gdal_type,
            automatically_determined_minimum_gdal_type=cls.int8bit.gdal_data_type_string,
        )
        return cls.int8bit.gdal_data_type_string
    if list_of_float_data_types or c_number_category == "GDT_Float":
        minimum_float_type = cls._get_minimum_float_type(
            list_of_float_data_types=list_of_float_data_types,
            list_of_integer=list_of_integer,
            minimum_required_datatype_list=minimum_gdal_type_list_converted,
        )
        cls.check_if_user_requested_data_type_deviates(
            user_defined_minimum_gdal_type=user_defined_minimum_gdal_type,
            automatically_determined_minimum_gdal_type=minimum_float_type,
        )
        return minimum_float_type
    if list_of_output_integers or c_number_category == "GDT_Int":
        if isinstance(user_defined_minimum_gdal_type_converted, str):
            user_defined_c_number_category = cls._determine_if_gdal_data_type_is_int_float_or_complex(
                user_defined_minimum_gdal_type_converted_list
            )
            if user_defined_c_number_category == "GDT_Int":
                user_defined_minimum_gdal_type_int = user_defined_minimum_gdal_type_converted
            else:
                user_defined_minimum_gdal_type_int = None
        else:
            user_defined_minimum_gdal_type_int = None

        minimum_integer_type = cls._get_valid_data_types_from_integer_list(
            int_and_bool_list=list_of_output_integers,
            minimum_integer_type_list=minimum_gdal_type_list_converted,
            user_defined_minimum_gdal_type=user_defined_minimum_gdal_type_int,
        )
        cls.check_if_user_requested_data_type_deviates(
            user_defined_minimum_gdal_type=user_defined_minimum_gdal_type,
            automatically_determined_minimum_gdal_type=minimum_integer_type,
        )
        return minimum_integer_type
    else:
        raise GeoKitCDataError("No datatypes could be determined.")