# Path: orangecontrib/imageanalytics/local_embedder.py
# class LocalEmbedder:
# 
#     embedder = None
# 
#     def __init__(self, model, model_settings):
#         self.model = model
#         self._load_model()
# 
#         self._target_image_size = model_settings["target_image_size"]
# 
#         self._session = cachecontrol.CacheControl(
#             requests.session(),
#             cache=cachecontrol.caches.FileCache(
#                 join(cache_dir(), __name__ + ".ImageEmbedder.httpcache")
#             ),
#         )
# 
#         self._cancelled = False
# 
#         self._image_loader = ImageLoader()
#         self._cache = EmbedderCache(model)
# 
#     def _load_model(self):
#         self.embedder = squeezenet(include_softmax=False)
# 
#     def embedd_data(self, file_paths, processed_callback=None):
#         all_embeddings = []
# 
#         for row in file_paths:
#             all_embeddings.append(self._embed(row))
#             if processed_callback:
#                 processed_callback(success=True)
# 
#         self._cache.persist_cache()
# 
#         return all_embeddings
# 
#     def _embed(self, file_path):
#         """ Load images and compute cache keys and send requests to
#         an http2 server for valid ones.
#         """
#         if self._cancelled:
#             raise EmbeddingCancelledException()
# 
#         image = self._image_loader.load_image_or_none(
#             file_path, self._target_image_size
#         )
#         if image is None:
#             return None
#         image = self._image_loader.preprocess_squeezenet(image)
# 
#         cache_key = self._cache.md5_hash(image)
#         cached_im = self._cache.get_cached_result_or_none(cache_key)
#         if cached_im is not None:
#             return cached_im
# 
#         embedded_image = self.embedder.predict([image])
#         embedded_image = embedded_image[0][0]
# 
#         self._cache.add(cache_key, embedded_image)
#         return embedded_image
# 
#     def set_cancelled(self):
#         self._cancelled = True
# 
# Path: orangecontrib/imageanalytics/server_embedder.py
# class ServerEmbedder(ServerEmbedderCommunicator):
#     def __init__(
#         self,
#         model_name: str,
#         max_parallel_requests: int,
#         server_url: str,
#         embbedder_type: str,
#         image_size: Tuple[int, int],
#     ) -> None:
#         super().__init__(
#             model_name, max_parallel_requests, server_url, embbedder_type
#         )
#         self.content_type = "image/jpeg"
#         self.image_size = image_size
#         self._image_loader = ImageLoader()
# 
#     async def _encode_data_instance(self, file_path: str) -> Optional[bytes]:
#         return self._image_loader.load_image_bytes(file_path, self.image_size)
# 
# Path: orangecontrib/imageanalytics/utils/image_utils.py
# def extract_paths(
#     data: Table, column: Union[DiscreteVariable, StringVariable]
# ) -> List[Optional[str]]:
#     """
#     Extract image/file paths from datatable column. If column has an origin attribute
#     it will be added as a prefix to the path otherwise just values of column will be
#     returned.
# 
#     Parameters
#     ----------
#     data
#         Table that have column with file paths/URL in metas
#     column
#         Variable which is a path attribute. Must be string or categorical
# 
#     Returns
#     -------
#     List of file paths or URLs
#     """
#     return [extract_image_path(inst, column) for inst in data]


from typing import Any, Callable, Dict, List, Optional, Tuple, Union
from Orange.data import ContinuousVariable, Domain, Table, Variable
from Orange.misc.utils.embedder_utils import EmbedderCache
from orangecontrib.imageanalytics.local_embedder import LocalEmbedder
from orangecontrib.imageanalytics.server_embedder import ServerEmbedder
from orangecontrib.imageanalytics.utils.image_utils import extract_paths
import numpy as np



MODELS = {
    "inception-v3": {
        "name": "Inception v3",
        "description": "Google's Inception v3 model trained on ImageNet.",
        "target_image_size": (299, 299),
        "layers": ["penultimate"],
        "order": 0,
        # batch size tell how many images we send in parallel, this number is
        # high for inception since it has many workers, but other embedders
        # send less images since bottleneck are workers, this way we avoid
        # ReadTimeout because of images waiting in a queue at the server

# Path: orangecontrib/imageanalytics/local_embedder.py
# class LocalEmbedder:
# 
#     embedder = None
# 
#     def __init__(self, model, model_settings):
#         self.model = model
#         self._load_model()
# 
#         self._target_image_size = model_settings["target_image_size"]
# 
#         self._session = cachecontrol.CacheControl(
#             requests.session(),
#             cache=cachecontrol.caches.FileCache(
#                 join(cache_dir(), __name__ + ".ImageEmbedder.httpcache")
#             ),
#         )
# 
#         self._cancelled = False
# 
#         self._image_loader = ImageLoader()
#         self._cache = EmbedderCache(model)
# 
#     def _load_model(self):
#         self.embedder = squeezenet(include_softmax=False)
# 
#     def embedd_data(self, file_paths, processed_callback=None):
#         all_embeddings = []
# 
#         for row in file_paths:
#             all_embeddings.append(self._embed(row))
#             if processed_callback:
#                 processed_callback(success=True)
# 
#         self._cache.persist_cache()
# 
#         return all_embeddings
# 
#     def _embed(self, file_path):
#         """ Load images and compute cache keys and send requests to
#         an http2 server for valid ones.
#         """
#         if self._cancelled:
#             raise EmbeddingCancelledException()
# 
#         image = self._image_loader.load_image_or_none(
#             file_path, self._target_image_size
#         )
#         if image is None:
#             return None
#         image = self._image_loader.preprocess_squeezenet(image)
# 
#         cache_key = self._cache.md5_hash(image)
#         cached_im = self._cache.get_cached_result_or_none(cache_key)
#         if cached_im is not None:
#             return cached_im
# 
#         embedded_image = self.embedder.predict([image])
#         embedded_image = embedded_image[0][0]
# 
#         self._cache.add(cache_key, embedded_image)
#         return embedded_image
# 
#     def set_cancelled(self):
#         self._cancelled = True
# 
# Path: orangecontrib/imageanalytics/server_embedder.py
# class ServerEmbedder(ServerEmbedderCommunicator):
#     def __init__(
#         self,
#         model_name: str,
#         max_parallel_requests: int,
#         server_url: str,
#         embbedder_type: str,
#         image_size: Tuple[int, int],
#     ) -> None:
#         super().__init__(
#             model_name, max_parallel_requests, server_url, embbedder_type
#         )
#         self.content_type = "image/jpeg"
#         self.image_size = image_size
#         self._image_loader = ImageLoader()
# 
#     async def _encode_data_instance(self, file_path: str) -> Optional[bytes]:
#         return self._image_loader.load_image_bytes(file_path, self.image_size)
# 
# Path: orangecontrib/imageanalytics/utils/image_utils.py
# def extract_paths(
#     data: Table, column: Union[DiscreteVariable, StringVariable]
# ) -> List[Optional[str]]:
#     """
#     Extract image/file paths from datatable column. If column has an origin attribute
#     it will be added as a prefix to the path otherwise just values of column will be
#     returned.
# 
#     Parameters
#     ----------
#     data
#         Table that have column with file paths/URL in metas
#     column
#         Variable which is a path attribute. Must be string or categorical
# 
#     Returns
#     -------
#     List of file paths or URLs
#     """
#     return [extract_image_path(inst, column) for inst in data]


# Path: orangecontrib/imageanalytics/image_embedder.py
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
from Orange.data import ContinuousVariable, Domain, Table, Variable
from Orange.misc.utils.embedder_utils import EmbedderCache
from orangecontrib.imageanalytics.local_embedder import LocalEmbedder
from orangecontrib.imageanalytics.server_embedder import ServerEmbedder
from orangecontrib.imageanalytics.utils.image_utils import extract_paths
import numpy as np




MODELS = {
    "inception-v3": {
        "name": "Inception v3",
        "description": "Google's Inception v3 model trained on ImageNet.",
        "target_image_size": (299, 299),
        "layers": ["penultimate"],
        "order": 0,
        # batch size tell how many images we send in parallel, this number is
        # high for inception since it has many workers, but other embedders
        # send less images since bottleneck are workers, this way we avoid
        # ReadTimeout because of images waiting in a queue at the server

        "batch_size": 500,