def apply_mask(data, mask, old_value, new_value, data_type, mask_type):
    """ A general masking function

    :param data: A data feature
    :type data: numpy.ndarray
    :param mask: A mask feature
    :type mask: numpy.ndarray
    :param old_value: An old value in data that will be replaced
    :type old_value: float
    :param new_value: A new value that will replace the old value in data
    :type new_value: float
    :param data_type: A data feature type
    :type data_type: FeatureType
    :param mask_type: A mask feature type
    :type mask_type: FeatureType
    """
    if not (data_type.is_spatial() and mask_type.is_spatial()):
        raise ValueError(
            'Masking with non-spatial data types is not yet supported')
    if data_type.is_timeless() and mask_type.is_time_dependent():
        raise ValueError(
            'Cannot mask timeless data feature with time dependent mask feature'
            )
    if data.shape[-3:-1] != mask.shape[-3:-1]:
        raise ValueError(
            'Data feature and mask feature have different spatial dimensions')
    if mask_type.is_time_dependent() and data.shape[0] != mask.shape[0]:
        raise ValueError(
            'Data feature and mask feature have different temporal dimensions')
    if mask.shape[-1] == data.shape[-1]:
        data[..., mask == old_value] = new_value
    elif mask.shape[-1] == 1:
        data[(...), (mask[..., 0] == old_value), :] = new_value
    else:
        raise ValueError(
            f'Mask feature has {mask.shape[-1]} number of bands while data feature has {data.shape[-1]} number of bands'
            )
    return data
