diff --git a/geti_sdk/data_models/annotation_scene.py b/geti_sdk/data_models/annotation_scene.py index db84f250..20433a1b 100644 --- a/geti_sdk/data_models/annotation_scene.py +++ b/geti_sdk/data_models/annotation_scene.py @@ -15,7 +15,7 @@ import copy import logging from pprint import pformat -from typing import Any, ClassVar, Dict, List, Optional, Sequence, Tuple, Union +from typing import Any, ClassVar, Dict, List, Optional, Sequence, Set, Tuple, Union import attr import cv2 @@ -311,6 +311,17 @@ def get_labels(self) -> List[Label]: labels.update(annotation.labels) return list(labels) + def get_label_names(self) -> List[str]: + """ + Return a list with the unique label names in the annotation scene. + + :return: List of label names + """ + label_names: Set[str] = set() + for label in self.get_labels(): + label_names.update([label.name]) + return list(label_names) + def apply_identifier( self, media_identifier: Union[ImageIdentifier, VideoFrameIdentifier] ) -> "AnnotationScene": diff --git a/geti_sdk/data_models/label.py b/geti_sdk/data_models/label.py index e4b824f3..9757071c 100644 --- a/geti_sdk/data_models/label.py +++ b/geti_sdk/data_models/label.py @@ -142,3 +142,21 @@ def from_label(cls, label: Label, probability: float) -> "ScoredLabel": return ScoredLabel( name=label.name, probability=probability, color=label.color, id=label.id ) + + def __key(self) -> Tuple[str, str]: + """ + Return a tuple representing the key of the ScoredLabel. + + The key is a tuple containing the name and color of the scored label. + + :return: A tuple representing the key of the label. + """ + return (self.name, self.color) + + def __hash__(self) -> int: + """ + Calculate the hash value of the object. + + :return: The hash value of the object. + """ + return hash(self.__key()) diff --git a/geti_sdk/deployment/deployed_model.py b/geti_sdk/deployment/deployed_model.py index 9ccaf640..34289d32 100644 --- a/geti_sdk/deployment/deployed_model.py +++ b/geti_sdk/deployment/deployed_model.py @@ -23,8 +23,8 @@ import attr import numpy as np -from openvino.model_api.adapters import OpenvinoAdapter, OVMSAdapter -from openvino.model_api.models import Model as model_api_Model +from model_api.adapters import OpenvinoAdapter, OVMSAdapter +from model_api.models import Model as model_api_Model from openvino.runtime import Core from packaging.version import Version @@ -227,10 +227,11 @@ def load_inference_model( :return: OpenVino inference engine model that can be used to make predictions on images """ + core = Core() if not target_device_is_ovms(device=device): # Run the model locally model_adapter = OpenvinoAdapter( - Core(), + core, model=os.path.join(self._model_data_path, "model.xml"), weights_path=os.path.join(self._model_data_path, "model.bin"), device=device, @@ -290,7 +291,8 @@ def load_inference_model( model = model_api_Model.create_model( model=model_adapter, model_type=model_type, - preload=True, + preload=False, + core=core, configuration=configuration, ) self._inference_model = model @@ -309,6 +311,14 @@ def load_inference_model( name: name for name in output_names } + # Force reload model to account for any postprocessing changes that may have + # been applied while creating the ModelAPI wrapper + logging.info( + f"Inference model wrapper initialized, force reloading model on device " + f"`{device}` to finalize inference model initialization process." + ) + self._inference_model.load(force=True) + @classmethod def from_model_and_hypers( cls, model: OptimizedModel, hyper_parameters: Optional[TaskConfiguration] = None diff --git a/geti_sdk/deployment/deployment.py b/geti_sdk/deployment/deployment.py index 6c502325..b3b81012 100644 --- a/geti_sdk/deployment/deployment.py +++ b/geti_sdk/deployment/deployment.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions # and limitations under the License. - +import datetime import json import logging import os @@ -20,7 +20,7 @@ import attr import numpy as np -from openvino.model_api.models import Model as OMZModel +from model_api.models import Model as OMZModel from geti_sdk.data_models import ( Annotation, @@ -36,6 +36,7 @@ from geti_sdk.rest_converters import ProjectRESTConverter from .deployed_model import DeployedModel +from .inference_hook_interfaces import PostInferenceHookInterface from .utils import OVMS_README_PATH, generate_ovms_model_name @@ -58,6 +59,7 @@ def __attrs_post_init__(self): self._inference_converters: Dict[str, Any] = {} self._path_to_temp_resources: Optional[str] = None self._requires_resource_cleanup: bool = False + self._post_inference_hooks: List[PostInferenceHookInterface] = [] self._empty_label: Optional[Label] = None @property @@ -109,6 +111,15 @@ def save(self, path_to_folder: Union[str, os.PathLike]) -> bool: with open(project_filepath, "w") as project_file: json.dump(project_dict, project_file, indent=4) + # Save post inference hooks, if any + if self.post_inference_hooks: + hook_config_file = os.path.join(deployment_folder, "hook_config.json") + hook_configs: List[Dict[str, Any]] = [] + for hook in self.post_inference_hooks: + hook_configs.append(hook.to_dict()) + with open(hook_config_file, "w") as file: + json.dump({"post_inference_hooks": hook_configs}, file) + # Clean up temp resources if needed if self._requires_resource_cleanup: self._remove_temporary_resources() @@ -145,7 +156,23 @@ def from_folder(cls, path_to_folder: Union[str, os.PathLike]) -> "Deployment": models.append( DeployedModel.from_folder(os.path.join(deployment_folder, task_folder)) ) - return cls(models=models, project=project) + deployment = cls(models=models, project=project) + + # Load post inference hooks, if any + hook_config_file = os.path.join(deployment_folder, "hook_config.json") + if os.path.isfile(hook_config_file): + available_hooks = { + subcls.__name__: subcls + for subcls in PostInferenceHookInterface.__subclasses__() + } + with open(hook_config_file, "r") as file: + hook_dict = json.load(file) + for hook_data in hook_dict["post_inference_hooks"]: + for hook_name, hook_args in hook_data.items(): + target_hook = available_hooks[hook_name] + hook = target_hook.from_dict(hook_args) + deployment.add_post_inference_hook(hook) + return deployment def load_inference_models(self, device: str = "CPU"): """ @@ -168,13 +195,15 @@ def load_inference_models(self, device: str = "CPU"): self._are_models_loaded = True logging.info(f"Inference models loaded on device `{device}` successfully.") - def infer(self, image: np.ndarray) -> Prediction: + def infer(self, image: np.ndarray, name: Optional[str] = None) -> Prediction: """ Run inference on an image for the full model chain in the deployment. :param image: Image to run inference on, as a numpy array containing the pixel data. The image is expected to have dimensions [height x width x channels], with the channels in RGB order + :param name: Optional name for the image, if specified this will be used in + any post inference hooks belonging to the deployment. :return: inference results """ self._check_models_loaded() @@ -201,10 +230,12 @@ def infer(self, image: np.ndarray) -> Prediction: ], ) ) - + self._execute_post_inference_hooks( + image=image, prediction=prediction, name=name + ) return prediction - def explain(self, image: np.ndarray) -> Prediction: + def explain(self, image: np.ndarray, name: Optional[str] = None) -> Prediction: """ Run inference on an image for the full model chain in the deployment. The resulting prediction will also contain saliency maps and the feature vector @@ -213,6 +244,8 @@ def explain(self, image: np.ndarray) -> Prediction: :param image: Image to run inference on, as a numpy array containing the pixel data. The image is expected to have dimensions [height x width x channels], with the channels in RGB order + :param name: Optional name for the image, if specified this will be used in + any post inference hooks belonging to the deployment. :return: inference results """ self._check_models_loaded() @@ -225,6 +258,9 @@ def explain(self, image: np.ndarray) -> Prediction: # Multi-task inference else: prediction = self._infer_pipeline(image=image, explain=True) + self._execute_post_inference_hooks( + image=image, prediction=prediction, name=name + ) return prediction def _check_models_loaded(self) -> None: @@ -450,3 +486,52 @@ def generate_ovms_config(self, output_folder: Union[str, os.PathLike]) -> None: f"file with instructions on how to launch OVMS, connect to it and run " f"inference. Please follow the instructions outlined there to get started." ) + + @property + def post_inference_hooks(self) -> List[PostInferenceHookInterface]: + """ + Return the currently active post inference hooks for the deployment + + :return: list of PostInferenceHook objects + """ + return self._post_inference_hooks + + def clear_inference_hooks(self) -> None: + """ + Remove all post inference hooks for the deployment + """ + n_hooks = len(self.post_inference_hooks) + self._post_inference_hooks = [] + if n_hooks != 0: + logging.info( + f"Post inference hooks cleared. {n_hooks} hooks were removed " + f"successfully" + ) + + def add_post_inference_hook(self, hook: PostInferenceHookInterface) -> None: + """ + Add a post inference hook, which will be executed after each call to + `Deployment.infer` + + :param hook: PostInferenceHook to be added to the deployment + """ + self._post_inference_hooks.append(hook) + logging.info(f"Hook `{hook}` added.") + logging.info( + f"Deployment now contains {len(self.post_inference_hooks)} " + f"post inference hooks." + ) + + def _execute_post_inference_hooks( + self, image: np.ndarray, prediction: Prediction, name: Optional[str] = None + ) -> None: + """ + Execute all post inference hooks + + :param image: Numpy image which was inferred + :param prediction: Prediction for the image + :param name: Optional name for the image + """ + timestamp = datetime.datetime.now() + for hook in self._post_inference_hooks: + hook.run(image, prediction, name, timestamp) diff --git a/geti_sdk/deployment/inference_hook_interfaces.py b/geti_sdk/deployment/inference_hook_interfaces.py new file mode 100644 index 00000000..55bdff22 --- /dev/null +++ b/geti_sdk/deployment/inference_hook_interfaces.py @@ -0,0 +1,232 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +import datetime +import inspect +import logging +from abc import ABCMeta, abstractmethod +from typing import Any, Dict, List, Optional + +import numpy as np + +from geti_sdk.data_models import Prediction + + +class PostInferenceObject(object, metaclass=ABCMeta): + """ + Base interface class for post inference triggers, actions and hooks + """ + + _override_from_dict_: bool = False + + def __new__(cls, *args, **kwargs): + """ + Create a new PostInferenceObject instance + """ + instance = super().__new__(cls) + instance._argument_dict_ = {"args": args, "kwargs": kwargs} + return instance + + def __init__(self): + self._constructor_arguments_ = self.__get_constructor_arguments() + + def __get_constructor_arguments(self) -> Dict[str, Any]: + """ + Return the arguments used for constructing the PostInferenceAction object + + :return: Dictionary containing the constructor parameter names as keys, and + parameter values as values + """ + constructor_argument_params = inspect.signature(self.__init__).parameters + parameters: Dict[str, Any] = {} + args = self._argument_dict_.get("args", ()) + kwargs = self._argument_dict_.get("kwargs", {}) + for index, (pname, parameter) in enumerate(constructor_argument_params.items()): + if index + 1 <= len(args): + parameters.update({pname: args[index]}) + elif pname in kwargs.keys(): + parameters.update({pname: kwargs[pname]}) + else: + parameters.update({pname: parameter.default}) + return parameters + + def to_dict(self) -> Dict[str, Any]: + """ + Return a dictionary representation of the PostInferenceObject + + :return: Dictionary representing the class name and its constructor parameters + """ + constructor_args: Dict[str, Any] = {} + for key, value in self._constructor_arguments_.items(): + if isinstance(value, PostInferenceObject): + constructor_args.update({key: value.to_dict()}) + else: + constructor_args.update({key: value}) + return {type(self).__name__: constructor_args} + + @classmethod + def from_dict(cls, input_dict: Dict[str, Any]) -> "PostInferenceObject": + """ + Construct a PostInferenceObject from an input dictionary `input_dict` + + :param input_dict: Dictionary representation of the PostInferenceObject + :return: Instantiated PostInferenceObject, according to the input dictionary + """ + available_objects = {subcls.__name__: subcls for subcls in cls.__subclasses__()} + pi_objects: List["PostInferenceObject"] = [] + for object_name, object_args in input_dict.items(): + target_object = available_objects[object_name] + if target_object._override_from_dict_: + pi_objects.append(target_object.from_dict(object_args)) + else: + pi_objects.append(target_object(**object_args)) + return pi_objects[0] + + +class PostInferenceTrigger(PostInferenceObject): + """ + Base class for post inference triggers + + Post inference triggers are used in inference hooks. They define a condition + (or set of conditions) that determines whether any post-inference action should be + taken. + + :param threshold: Threshold to use in activating the trigger. If the computed + score is above the threshold, the trigger emits a positive decision and any + downstream actions will be performed + """ + + def __init__(self, threshold: float = 0.5): + super().__init__() + self.threshold = threshold + self._repr_info_ = f"threshold={threshold:.1f}" + + @abstractmethod + def __call__(self, image: np.ndarray, prediction: Prediction) -> float: + """ + Compute a trigger score for the `image` and corresponding `prediction`. + + :param image: Numpy array representing an image + :param prediction: Prediction object corresponding to the inference result + for the image. + :return: Float representing the score for the input + """ + return NotImplemented + + def get_decision(self, score: float) -> bool: + """ + Make a decision based on a previously computed `score` and the threshold defined + for the trigger + + :param score: Float representing the score for a certain image, prediction pair + :return: Boolean indicating whether the trigger conditions are met (True, + score is higher than the threshold), or not (False) + """ + return score > self.threshold + + def __repr__(self) -> str: + """ + Return string representation of the PostInferenceTrigger + """ + return f"{type(self).__name__}({self._repr_info_})" + + +class PostInferenceAction(PostInferenceObject): + """ + Base class for post inference actions. These are actions that are used in inference + hooks, and can be (conditionally) executed after inference + + :param log_level: Log level to use in the action, current options are `info` or + `debug`. Defaults to `debug` + """ + + def __init__(self, log_level: str = "debug"): + super().__init__() + if log_level.lower() == "debug": + self.log_function = logging.debug + elif log_level.lower() == "info": + self.log_function = logging.info + else: + raise ValueError( + f"Unsupported log_level `{log_level}`, options are 'info' or 'debug'." + ) + self._repr_info_: str = "" + + @abstractmethod + def __call__( + self, + image: np.ndarray, + prediction: Prediction, + score: Optional[float] = None, + name: Optional[str] = None, + timestamp: Optional[datetime.datetime] = None, + ): + """ + Execute the action for the given `image` with corresponding `prediction` and an + `score`. The `score` could be passed from the trigger that triggers the action. + + :param image: Numpy array representing an image + :param prediction: Prediction object which was generated for the image + :param score: Optional score computed from a post inference trigger + :param name: String containing the name of the image + :param timestamp: Datetime object containing the timestamp belonging to the + image + """ + return NotImplemented + + def __repr__(self) -> str: + """ + Return string representation of the PostInferenceAction + """ + return f"{type(self).__name__}({self._repr_info_})" + + +class PostInferenceHookInterface(PostInferenceObject): + """ + Basic hook that can be executed after inference. A PostInferenceHook consists of: + - A Trigger, defining a condition + - An Action, defining an act or sequence of actions to perform when the + trigger is activated. + + + :param trigger: PostInferenceTrigger which is evaluated and used to trigger the + hook action + :param action: PostInferenceAction to be executed if triggered + """ + + def __init__(self, trigger: PostInferenceTrigger, action: PostInferenceAction): + super().__init__() + self.trigger = trigger + self.action = action + + @abstractmethod + def run( + self, + image: np.ndarray, + prediction: Prediction, + name: Optional[str] = None, + timestamp: Optional[datetime.datetime] = None, + ) -> None: + """ + Execute the post inference hook. This will first evaluate the `trigger`, and + if the trigger conditions are met the corresponding `action` will be executed. + + :param image: Numpy array representing the image that was the input for + model inference + :param prediction: Prediction object containing the inference results for the + image + :param name: Optional name of the image which can be used in the hook + action, for example as filename or tag for data collection + :param timestamp: Optional timestamp belonging to the image + """ + raise NotImplementedError diff --git a/geti_sdk/deployment/predictions_postprocessing/results_converter/results_to_prediction_converter.py b/geti_sdk/deployment/predictions_postprocessing/results_converter/results_to_prediction_converter.py index 27d79f5d..a5fc6ff6 100644 --- a/geti_sdk/deployment/predictions_postprocessing/results_converter/results_to_prediction_converter.py +++ b/geti_sdk/deployment/predictions_postprocessing/results_converter/results_to_prediction_converter.py @@ -19,7 +19,7 @@ import cv2 import numpy as np -from openvino.model_api.models.utils import ( +from model_api.models.utils import ( AnomalyResult, ClassificationResult, DetectionResult, diff --git a/geti_sdk/deployment/predictions_postprocessing/utils/detection_utils.py b/geti_sdk/deployment/predictions_postprocessing/utils/detection_utils.py index 405126c9..cb4cfcb8 100644 --- a/geti_sdk/deployment/predictions_postprocessing/utils/detection_utils.py +++ b/geti_sdk/deployment/predictions_postprocessing/utils/detection_utils.py @@ -17,7 +17,7 @@ from typing import Any, Dict, List import numpy as np -from openvino.model_api.models.utils import Detection +from model_api.models.utils import Detection from geti_sdk.data_models.model import Model diff --git a/geti_sdk/post_inference_hooks/__init__.py b/geti_sdk/post_inference_hooks/__init__.py new file mode 100644 index 00000000..bc3880b7 --- /dev/null +++ b/geti_sdk/post_inference_hooks/__init__.py @@ -0,0 +1,38 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +""" +PostInferenceHooks are used to construct pipelines for e.g. data collection or other +actions based on inference outcomes. +""" +from .actions import FileSystemDataCollection, GetiDataCollection, HttpRequestAction +from .post_inference_hook import PostInferenceHook +from .triggers import ( + AlwaysTrigger, + ConfidenceTrigger, + EmptyLabelTrigger, + LabelTrigger, + ObjectCountTrigger, +) + +__all__ = [ + "PostInferenceHook", + "ConfidenceTrigger", + "LabelTrigger", + "EmptyLabelTrigger", + "ObjectCountTrigger", + "AlwaysTrigger", + "GetiDataCollection", + "FileSystemDataCollection", + "HttpRequestAction", +] diff --git a/geti_sdk/post_inference_hooks/actions/__init__.py b/geti_sdk/post_inference_hooks/actions/__init__.py new file mode 100644 index 00000000..8a3c05f4 --- /dev/null +++ b/geti_sdk/post_inference_hooks/actions/__init__.py @@ -0,0 +1,19 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +"""Actions that can be used in post inference hooks""" +from .file_system_data_collection import FileSystemDataCollection +from .geti_data_collection import GetiDataCollection +from .http_request_action import HttpRequestAction + +__all__ = ["GetiDataCollection", "FileSystemDataCollection", "HttpRequestAction"] diff --git a/geti_sdk/post_inference_hooks/actions/file_system_data_collection.py b/geti_sdk/post_inference_hooks/actions/file_system_data_collection.py new file mode 100644 index 00000000..ed4b9428 --- /dev/null +++ b/geti_sdk/post_inference_hooks/actions/file_system_data_collection.py @@ -0,0 +1,162 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +import json +import logging +import os +from datetime import datetime +from typing import Optional + +import cv2 +import numpy as np + +from geti_sdk.data_models import Prediction +from geti_sdk.deployment.inference_hook_interfaces import PostInferenceAction +from geti_sdk.rest_converters import PredictionRESTConverter +from geti_sdk.utils import show_image_with_annotation_scene + + +class FileSystemDataCollection(PostInferenceAction): + """ + Post inference action that will save an image to a specified folder on disk. The + prediction output and trigger score that triggered the action are also saved. + + The data is saved in the `target_folder`, in which the action will create the + following folder structure: + + + | + |- images + |- predictions + |- scores + + :param target_folder: Target folder on disk where the inferred images should be + saved. If it does not exist yet, this action will create it. + :param file_name_prefix: Prefix to use for the files that will be saved by this + action. Default is 'image' + :param save_predictions: True to save the predictions for each image as well, in + addition to the image itself. Set to False to not store any predictions + :param save_scores: True to save the trigger score for each image as well, in + addition to the image itself. Set to False to not save any scores. + :param log_level: Log level for the action. Options are 'info' or 'debug' + """ + + def __init__( + self, + target_folder: str, + file_name_prefix: str = "", + save_predictions: bool = True, + save_scores: bool = True, + save_overlays: bool = True, + log_level: str = "debug", + ): + super().__init__(log_level=log_level) + + self.image_path = os.path.join(target_folder, "images") + folders_to_create = [self.image_path] + if save_predictions: + self.predictions_path = os.path.join(target_folder, "predictions") + folders_to_create.append(self.predictions_path) + if save_scores: + self.scores_path = os.path.join(target_folder, "scores") + folders_to_create.append(self.scores_path) + if save_overlays: + self.overlays_path = os.path.join(target_folder, "overlays") + folders_to_create.append(self.overlays_path) + + for path in folders_to_create: + os.makedirs(path, exist_ok=True, mode=0o770) + + self.prefix = file_name_prefix + self.save_predictions = save_predictions + self.save_scores = save_scores + self.save_overlays = save_overlays + + self._repr_info_ = ( + f"target_folder=`{target_folder}`, " + f"file_prefix={file_name_prefix}, " + f"save_predictions={save_predictions}, " + f"save_scores={save_scores}, " + f"save_overlays={save_overlays}" + ) + + def __call__( + self, + image: np.ndarray, + prediction: Prediction, + score: Optional[float] = None, + name: Optional[str] = None, + timestamp: Optional[datetime] = None, + ): + """ + Execute the action, save the given `image` to the predefined target folder. + The `prediction` and `score` are also saved. + + :param image: Numpy array representing an image + :param prediction: Prediction object which was generated for the image + :param score: Optional score computed from a post inference trigger + :param name: String containing the name of the image + :param timestamp: Datetime object containing the timestamp belonging to the + image + """ + image_bgr = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) + # we use cv2 to encode the numpy array as image, so it expects an + # image in BGR format. However, `Deployment.infer` requires RGB format, so + # we have to convert + if name is None: + name = self.prefix + else: + name = self.prefix + name + if timestamp is None: + timestamp = datetime.now() + + filename = name + "_" + timestamp.strftime("%Y%m%dT%H-%M-%S-%f") + + success = cv2.imwrite( + os.path.join(self.image_path, filename + ".png"), image_bgr + ) + if not success: + logging.error( + f"Failed to save image `{filename}.png` to folder `{self.image_path}`." + ) + + try: + if self.save_predictions: + prediction_filepath = os.path.join( + self.predictions_path, filename + ".json" + ) + with open(prediction_filepath, "w") as file: + prediction_dict = PredictionRESTConverter.to_dict(prediction) + json.dump(prediction_dict, fp=file) + + if self.save_scores: + if score is not None: + score_filepath = os.path.join(self.scores_path, filename + ".txt") + with open(score_filepath, "w") as file: + file.write(f"{score}") + + if self.save_overlays: + overlay_path = os.path.join(self.overlays_path, filename + ".jpg") + show_image_with_annotation_scene( + image=image, + annotation_scene=prediction, + filepath=overlay_path, + show_results=False, + ) + except Exception as e: + logging.exception(e, stack_info=True, exc_info=True) + + self.log_function( + f"FileSystemDataCollection inference action saved image data to folder " + f"`{self.image_path}`" + ) diff --git a/geti_sdk/post_inference_hooks/actions/geti_data_collection.py b/geti_sdk/post_inference_hooks/actions/geti_data_collection.py new file mode 100644 index 00000000..c51ce973 --- /dev/null +++ b/geti_sdk/post_inference_hooks/actions/geti_data_collection.py @@ -0,0 +1,173 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +import copy +import logging +import warnings +from datetime import datetime +from typing import Any, Dict, Optional, Union + +import attrs +import cv2 +import numpy as np + +from geti_sdk.data_models import Dataset, Prediction, Project +from geti_sdk.deployment.inference_hook_interfaces import PostInferenceAction +from geti_sdk.http_session import ( + GetiRequestException, + GetiSession, + ServerCredentialConfig, + ServerTokenConfig, +) +from geti_sdk.rest_clients.dataset_client import DatasetClient +from geti_sdk.rest_clients.media_client.image_client import ImageClient +from geti_sdk.rest_clients.project_client.project_client import ProjectClient + + +class GetiDataCollection(PostInferenceAction): + """ + Post inference action that will send an image to a specified `project` and `dataset` + on the Intel® Geti™ server addressed by `session`. + + :param session: Geti session representing the connecting to the Intel® Geti™ server + :param workspace_id: unique ID of the workspace in which the project to collect + the data resides. + :param project: Project or name of the project to whicht the image data should be + transferred. + :param dataset: Optional Dataset or name of the dataset in which to store the + image data. If not specified, the default training dataset of the project is + used + :param log_level: Log level for the action. Options are 'info' or 'debug' + """ + + _override_from_dict_: bool = True + + def __init__( + self, + session: GetiSession, + workspace_id: str, + project: Union[str, Project], + dataset: Optional[Union[str, Dataset]] = None, + log_level: str = "debug", + ): + super().__init__(log_level=log_level) + project_client = ProjectClient(session=session, workspace_id=workspace_id) + if isinstance(project, str): + project_name = project + project = project_client.get_project_by_name(project_name=project_name) + if project is None: + raise ValueError( + f"Project `{project_name}` does not exist on the Intel® Geti™ " + f"server, unable to initialize the Intel® Geti™ data collection " + f"action" + ) + dataset_client = DatasetClient( + session=session, workspace_id=workspace_id, project=project + ) + if dataset is None: + datasets = dataset_client.get_all_datasets() + dataset = [ds for ds in datasets if ds.use_for_training][0] + elif isinstance(dataset, str): + dataset_name = dataset + + try: + dataset = dataset_client.get_dataset_by_name(dataset_name) + except ValueError: + dataset = dataset_client.create_dataset(dataset_name) + self.log_function( + f"Dataset `{dataset_name}` was created in project `{project.name}`" + ) + self.image_client = ImageClient( + session=session, workspace_id=workspace_id, project=project + ) + self.dataset = dataset + self._repr_info_ = ( + f"target_server=`{session.config.host}`, " + f"target_project={project.name}, " + f"target_dataset={dataset.name}" + ) + + # Serialize input arguments + self._constructor_arguments_["project"] = project.name + self._constructor_arguments_["dataset"] = dataset.name + self._constructor_arguments_["session"] = attrs.asdict(session.config) + + def __call__( + self, + image: np.ndarray, + prediction: Prediction, + score: Optional[float] = None, + name: Optional[str] = None, + timestamp: Optional[datetime] = None, + ): + """ + Execute the action, upload the given `image` to the Intel® Geti™ server. + + The parameters `prediction`, `score`, `name` and `timestamp` are not used in + this specific action. + + :param image: Numpy array representing an image + :param prediction: Prediction object which was generated for the image + :param score: Optional score computed from a post inference trigger + :param name: String containing the name of the image + :param timestamp: Datetime object containing the timestamp belonging to the + image + """ + image_bgr = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) + # upload_image uses cv2 to encode the numpy array as image, so it expects an + # image in BGR format. However, `Deployment.infer` requires RGB format, so + # we have to convert + try: + self.image_client.upload_image(image=image_bgr, dataset=self.dataset) + except GetiRequestException as e: + logging.exception(e) + self.log_function( + f"GetiDataCollection inference action uploaded image to dataset " + f"`{self.dataset.name}`" + ) + + @classmethod + def from_dict(cls, input_dict: Dict[str, Any]) -> "GetiDataCollection": + """ + Construct a GetiDataCollection post inference action object from an input + dictionary `input_dict` + + :param input_dict: Dictionary representation of the GetiDataCollection + :return: Instantiated GetiDataCollection, according to the input dictionary + """ + input_copy = copy.deepcopy(input_dict) + session_dict = input_copy["session"] + if "username" in session_dict: + server_config_class = ServerCredentialConfig + elif "token" in session_dict: + server_config_class = ServerTokenConfig + else: + raise ValueError( + f"Invalid `GetiSession` parameters encountered: {session_dict}" + ) + session = GetiSession(server_config_class(**session_dict)) + input_copy.update({"session": session}) + return cls(**input_copy) + + def to_dict(self) -> Dict[str, Any]: + """ + Return a dictionary representation of the PostInferenceObject + + :return: Dictionary representing the class name and its constructor parameters + """ + warnings.warn( + "GetiDataCollection post inference action contains sensitive information " + "used for authentication on the Intel® Geti™ platform. Be careful when " + "saving this information to disk or sharing with others!" + ) + return super().to_dict() diff --git a/geti_sdk/post_inference_hooks/actions/http_request_action.py b/geti_sdk/post_inference_hooks/actions/http_request_action.py new file mode 100644 index 00000000..d7a6ce37 --- /dev/null +++ b/geti_sdk/post_inference_hooks/actions/http_request_action.py @@ -0,0 +1,87 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +from datetime import datetime +from typing import Dict, Optional + +import numpy as np +import requests + +from geti_sdk.data_models import Prediction +from geti_sdk.deployment.inference_hook_interfaces import PostInferenceAction +from geti_sdk.rest_converters import PredictionRESTConverter + + +class HttpRequestAction(PostInferenceAction): + """ + Post inference action that will send an http request to a specified `url`. + + :param url: Full URL to send the request to + :param method: HTTP method to use, for example `GET` or `POST` + :param headers: Headers to use in the request, can be used for instance for + authentication purposes + :param include_prediction_data: Set this to True to include the prediction data in + the body of the request. Only applicable for POST requests + :param log_level: Log level for the action. Options are 'info' or 'debug' + """ + + def __init__( + self, + url: str, + method: str = "GET", + headers: Optional[Dict[str, str]] = None, + include_prediction_data: bool = False, + log_level: str = "info", + ): + super().__init__(log_level=log_level) + + self.url = url + self.method = method + self.headers = headers + + self.include_data = include_prediction_data and method == "POST" + + self._repr_info_ = ( + f"url=`{url}`, " + f"method={method}, " + f"headers={headers}, " + f"include_data={self.include_data}" + ) + + def __call__( + self, + image: np.ndarray, + prediction: Prediction, + score: Optional[float] = None, + name: Optional[str] = None, + timestamp: Optional[datetime] = None, + ): + """ + Execute the action, send an HTTP request to the predefined url + + :param image: Numpy array representing an image + :param prediction: Prediction object which was generated for the image + :param score: Optional score computed from a post inference trigger + :param name: String containing the name of the image + :param timestamp: Datetime object containing the timestamp belonging to the + image + """ + data = None + if self.include_data: + prediction_dict = PredictionRESTConverter.to_dict(prediction) + data = prediction_dict + + requests.request( + method=self.method, url=self.url, headers=self.headers, data=data + ) + self.log_function(f"HTTP {self.method} request send to `{self.url}`.") diff --git a/geti_sdk/post_inference_hooks/post_inference_hook.py b/geti_sdk/post_inference_hooks/post_inference_hook.py new file mode 100644 index 00000000..7ae0baab --- /dev/null +++ b/geti_sdk/post_inference_hooks/post_inference_hook.py @@ -0,0 +1,194 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +import copy +import datetime +import logging +from concurrent.futures import ThreadPoolExecutor +from threading import BoundedSemaphore +from typing import Any, Dict, Optional + +import numpy as np + +from geti_sdk.data_models import Prediction +from geti_sdk.deployment.inference_hook_interfaces import ( + PostInferenceAction, + PostInferenceHookInterface, + PostInferenceTrigger, +) +from geti_sdk.post_inference_hooks.utils import RateLimiter + + +class PostInferenceHook(PostInferenceHookInterface): + """ + Basic hook that can be executed after inference. A PostInferenceHook consists of: + - A Trigger, defining a condition + - An Action, defining an act or sequence of actions to perform when the + trigger is activated. + + By default, hooks are executed in parallel in a separate thread from the main + inference code. If you want to disable parallel execution, make sure to set + `max_threads=0` when creating the hook. + + :param trigger: PostInferenceTrigger which is evaluated and used to trigger the + hook action + :param action: PostInferenceAction to be executed if triggered + :param max_threads: Maximum number of threads to use for hook execution. Defaults + to 5. Set to 0 to disable parallel hook execution. + :param limit_action_rate: True to limit the rate at which the `action` for the + hook is executed. Note that rate limiting is applied **after** trigger + evaluation, so this can be useful for handling video streaming in which + subsequent frames may be very similar. Enabling rate limiting will avoid + sampling many near-duplicate frames + :param max_frames_per_second: Maximum frame rate at which to execute the action. + Only takes effect if `limit_action_rate = True`. + :param queue_limit: Maximum size of the execution queue for the hook. If left as 0 + (the default), the queue is unbounded. This may lead to high memory usage in + some cases (if inference is very fast, or the action execution is slow). When + running into out of memory issues, try setting the queue limit to avoid + buffering too many frames in memory. Note that this may slow down the + inference rate + """ + + def __init__( + self, + trigger: PostInferenceTrigger, + action: PostInferenceAction, + max_threads: int = 5, + limit_action_rate: bool = False, + max_frames_per_second: float = 1, + queue_limit: int = 0, + ): + super().__init__(trigger=trigger, action=action) + + self.parallel_execution = max_threads != 0 + self._semaphore: Optional[BoundedSemaphore] = None + + if self.parallel_execution: + self.executor = ThreadPoolExecutor(max_workers=max_threads) + logging.debug( + f"Parallel inference hook execution enabled, using a maximum of " + f"{max_threads} threads." + ) + if queue_limit > 0: + self._semaphore = BoundedSemaphore(queue_limit + max_threads) + + if limit_action_rate: + self.rate_limiter: Optional[RateLimiter] = RateLimiter( + frames_per_second=max_frames_per_second, is_blocking=False + ) + else: + self.rate_limiter = None + + def run( + self, + image: np.ndarray, + prediction: Prediction, + name: Optional[str] = None, + timestamp: Optional[datetime.datetime] = None, + ) -> None: + """ + Run the post inference hook. First evaluate the trigger, then execute the + action if the trigger conditions are met. + + :param image: Numpy array representing the image + :param prediction: Prediction object containing the inference results for the + image + :param name: Optional name of the image which can be used in the hook + action, for example as filename or tag for data collection + :param timestamp: Optional timestamp belonging to the image + """ + + def execution_function( + im: np.ndarray, pred: Prediction, ts: datetime.datetime + ) -> None: + score = self.trigger(image=im, prediction=pred) + decision = self.trigger.get_decision(score=score) + if decision: + if self.rate_limiter is not None: + take_action = next(self.rate_limiter) + else: + take_action = True + if take_action: + self.action( + image=im, prediction=pred, score=score, name=name, timestamp=ts + ) + + if timestamp is None: + timestamp = datetime.datetime.now() + if self.parallel_execution: + if self._semaphore is not None: + self._semaphore.acquire() + try: + future = self.executor.submit( + execution_function, image, prediction, timestamp + ) + except Exception as error: + if self._semaphore is not None: + self._semaphore.release() + raise error + if self._semaphore is not None: + future.add_done_callback(lambda x: self._semaphore.release()) + else: + execution_function(image, prediction, timestamp) + + def __del__(self): + """ + Await shutdown of the ThreadPoolExecutor, if needed. + + Called upon deletion of the post inference hook or garbage collection + """ + if self.parallel_execution: + self.executor.shutdown(wait=True) + + def __repr__(self) -> str: + """ + Return a string representation of the PostInferenceHook object + + :return: String representing the post inference hook + """ + rate_msg = "" + if self.rate_limiter is not None: + rate_msg = ( + f"Action rate limited to {1/self.rate_limiter.interval:.1f} " + f"frames per second." + ) + thread_msg = "" + if self.parallel_execution: + thread_msg = "Multithreaded execution enabled." + + suffix_msg = f"[{thread_msg} {rate_msg}]" + if len(suffix_msg) == 3: + suffix_msg = "" + return f"PostInferenceHook(trigger={self.trigger}, action={self.action}){suffix_msg}" + + @classmethod + def from_dict(cls, input_dict: Dict[str, Any]) -> "PostInferenceHook": + """ + Create a PostInferenceHook object from it's dictionary representation + + :param input_dict: Dictionary representing the hook + :return: Initialized PostInferenceHook object, with a trigger and action set + according to the input dictionary + """ + input_copy = copy.deepcopy(input_dict) + + # Construct trigger + trigger = PostInferenceTrigger.from_dict(input_copy["trigger"]) + input_copy.update({"trigger": trigger}) + + # Construct action + action = PostInferenceAction.from_dict(input_copy["action"]) + input_copy.update({"action": action}) + + return cls(**input_copy) diff --git a/geti_sdk/post_inference_hooks/triggers/__init__.py b/geti_sdk/post_inference_hooks/triggers/__init__.py new file mode 100644 index 00000000..31fdbe8f --- /dev/null +++ b/geti_sdk/post_inference_hooks/triggers/__init__.py @@ -0,0 +1,27 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +"""Triggers that can be used in post inference hooks""" +from .always_trigger import AlwaysTrigger +from .confidence_trigger import ConfidenceTrigger +from .empty_label_trigger import EmptyLabelTrigger +from .label_trigger import LabelTrigger +from .object_count_trigger import ObjectCountTrigger + +__all__ = [ + "AlwaysTrigger", + "ConfidenceTrigger", + "LabelTrigger", + "EmptyLabelTrigger", + "ObjectCountTrigger", +] diff --git a/geti_sdk/post_inference_hooks/triggers/always_trigger.py b/geti_sdk/post_inference_hooks/triggers/always_trigger.py new file mode 100644 index 00000000..dddd528a --- /dev/null +++ b/geti_sdk/post_inference_hooks/triggers/always_trigger.py @@ -0,0 +1,38 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +import numpy as np + +from geti_sdk.data_models import Prediction +from geti_sdk.deployment.inference_hook_interfaces import PostInferenceTrigger + + +class AlwaysTrigger(PostInferenceTrigger): + """ + Post inference trigger that activates on each inference call. + """ + + def __init__(self): + super().__init__() + self._repr_info_ = "" + + def __call__(self, image: np.ndarray, prediction: Prediction) -> float: + """ + Compute a trigger score for the `image` and corresponding `prediction`. + + :param image: Numpy array representing an image + :param prediction: Prediction object corresponding to the inference result + for the image. + :return: Float representing the score for the input + """ + return 1 diff --git a/geti_sdk/post_inference_hooks/triggers/confidence_trigger.py b/geti_sdk/post_inference_hooks/triggers/confidence_trigger.py new file mode 100644 index 00000000..693124f8 --- /dev/null +++ b/geti_sdk/post_inference_hooks/triggers/confidence_trigger.py @@ -0,0 +1,72 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +from typing import List, Optional + +import numpy as np + +from geti_sdk.data_models import Prediction +from geti_sdk.deployment.inference_hook_interfaces import PostInferenceTrigger + + +class ConfidenceTrigger(PostInferenceTrigger): + """ + Post inference trigger based on the confidence of the predictions for an image. + If the prediction confidence is **lower** than the defined `threshold`, the trigger + is activated. + + Optionally a list of `label_names` can be defined, if passed then only the + confidence level for the specified labels will be considered + + :param threshold: Confidence threshold to consider. Any predictions with a + confidence **lower** than this threshold will activate the trigger + :param label_names: Optional list of label names to include. If passed, only the + confidences for the specified labels will be considered. + """ + + def __init__(self, threshold: float = 0.5, label_names: Optional[List[str]] = None): + super().__init__(threshold=threshold) + self.label_names = label_names + + if label_names is not None: + self._repr_info_ += f", label_names={label_names}" + + def __call__(self, image: np.ndarray, prediction: Prediction) -> float: + """ + Compute a trigger score for the `image` and corresponding `prediction`. + + :param image: Numpy array representing an image + :param prediction: Prediction object corresponding to the inference result + for the image. + :return: Float representing the score for the input + """ + min_confidence: float = 1 + for predicted_object in prediction.annotations: + for label in predicted_object.labels: + if self.label_names is not None: + if label.name not in self.label_names: + continue + if label.probability < min_confidence: + min_confidence = label.probability + return min_confidence + + def get_decision(self, score: float) -> bool: + """ + Make a decision based on a previously computed `score` and the threshold defined + for the trigger + + :param score: Float representing the score for a certain image, prediction pair + :return: Boolean indicating whether the trigger conditions are met (True, + score is **lower** than the threshold), or not (False) + """ + return score < self.threshold diff --git a/geti_sdk/post_inference_hooks/triggers/empty_label_trigger.py b/geti_sdk/post_inference_hooks/triggers/empty_label_trigger.py new file mode 100644 index 00000000..63618706 --- /dev/null +++ b/geti_sdk/post_inference_hooks/triggers/empty_label_trigger.py @@ -0,0 +1,50 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +import numpy as np + +from geti_sdk.data_models import Prediction +from geti_sdk.deployment.inference_hook_interfaces import PostInferenceTrigger + + +class EmptyLabelTrigger(PostInferenceTrigger): + """ + Post inference trigger that will activate if the prediction is empty + """ + + def __init__(self): + # LabelTrigger will return a score of 1 if label is found, so we can use the + # default threshold defined in the super class + super().__init__() + self._repr_info_ = "" + + def __call__(self, image: np.ndarray, prediction: Prediction) -> float: + """ + Compute a trigger score for the `image` and corresponding `prediction`. + + :param image: Numpy array representing an image + :param prediction: Prediction object corresponding to the inference result + for the image. + :return: Float representing the score for the input + """ + for predicted_object in prediction.annotations: + if len(predicted_object.labels) > 1: + return 0 + if not predicted_object.shape.is_full_box( + image_width=image.shape[1], image_height=image.shape[0] + ): + return 0 + for label in predicted_object.labels: + if label.name.lower() == "no object": + return 1 + return 0 diff --git a/geti_sdk/post_inference_hooks/triggers/label_trigger.py b/geti_sdk/post_inference_hooks/triggers/label_trigger.py new file mode 100644 index 00000000..62b03fbc --- /dev/null +++ b/geti_sdk/post_inference_hooks/triggers/label_trigger.py @@ -0,0 +1,62 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +from typing import List + +import numpy as np + +from geti_sdk.data_models import Prediction +from geti_sdk.deployment.inference_hook_interfaces import PostInferenceTrigger + + +class LabelTrigger(PostInferenceTrigger): + """ + Post inference trigger based on the presence of certain label(s) in the + predictions for an image. + If the specified label or labels are in the prediction results for an inferred + image, the trigger is activated. + + :param label_names: List of label names to search for. If any of + :param mode: Operation mode to use when evaluating the labels. Supported modes are: + - `OR` (the default) -> If **any** of the labels in `label_names` if found in + the prediction, the trigger activates. + - `AND` -> If and only if **all** of the labels in `label_names` are + predicted within the image, the trigger activates + """ + + def __init__(self, label_names: List[str], mode: str = "OR"): + self.label_names = set(label_names) + self.mode = mode + + # LabelTrigger will return a score of 1 if label is found, so we can use the + # default threshold defined in the super class + super().__init__() + self._repr_info_ = f"label_names={label_names}" + self._repr_info_ += f", mode={mode}" + + def __call__(self, image: np.ndarray, prediction: Prediction) -> float: + """ + Compute a trigger score for the `image` and corresponding `prediction`. + + :param image: Numpy array representing an image + :param prediction: Prediction object corresponding to the inference result + for the image. + :return: Float representing the score for the input + """ + predicted_labels = set() + for label in prediction.get_labels(): + predicted_labels.add(label.name) + if self.mode == "AND": + return float(self.label_names.issubset(predicted_labels)) + else: # mode == "OR" + return float(not self.label_names.isdisjoint(predicted_labels)) diff --git a/geti_sdk/post_inference_hooks/triggers/object_count_trigger.py b/geti_sdk/post_inference_hooks/triggers/object_count_trigger.py new file mode 100644 index 00000000..4ee10f5a --- /dev/null +++ b/geti_sdk/post_inference_hooks/triggers/object_count_trigger.py @@ -0,0 +1,113 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +from typing import List, Optional + +import numpy as np + +from geti_sdk.data_models import Prediction +from geti_sdk.deployment.inference_hook_interfaces import PostInferenceTrigger + +SUPPORTED_MODES = ["greater", "lower", "equal"] + + +class ObjectCountTrigger(PostInferenceTrigger): + """ + Post inference trigger based on the number of predicted objects in an image. + + The operation mode of the trigger can be specified: It will activate either if the + object count is above the threshold, below the threshold or exactly equal to the + threshold value. This behaviour can be controlled via the `mode` parameter. + + :param threshold: Threshold value for the total number of objects in a prediction + :param label_names: Optional list of classes/labels to account for in the object + counting. If specified, only objects with those labels will count towards the + total + :param mode: Operation mode for the trigger, which defines when the trigger will + activate. Options are: + + - `greater` -> Trigger activates if object count is greater than threshold + - `lower` -> Trigger activates if object count is lower than threshold + - `equal` -> Trigger activates if object count is equal to threshold + + Defaults to `greater` + """ + + def __init__( + self, + threshold: int = 1, + label_names: Optional[List[str]] = None, + mode: str = "greater", + ): + super().__init__(threshold=threshold) + self.label_names = label_names + self.filter_labels = False + + if label_names is not None: + self.filter_labels = True + self._repr_info_ += f", label_names={label_names}" + + lower_mode = mode.lower() + if lower_mode not in SUPPORTED_MODES: + raise ValueError( + f"Invalid mode `{mode}`. Valid options are: {SUPPORTED_MODES}" + ) + self.mode = lower_mode + self._repr_info_ += f", mode={lower_mode}" + + def __call__(self, image: np.ndarray, prediction: Prediction) -> float: + """ + Compute a trigger score for the `image` and corresponding `prediction`. + + :param image: Numpy array representing an image + :param prediction: Prediction object corresponding to the inference result + for the image. + :return: Float representing the score for the input + """ + if not self.filter_labels: + n_objects = len(prediction.annotations) + if n_objects != 1: + return n_objects + else: + # Prediction might be a 'No object', we have to check for this + predicted_labels = prediction.annotations[0].labels + if len(predicted_labels) > 1: + return 1.0 + else: + if predicted_labels[0].name.lower() == "no object": + return 0.0 + else: + return 1.0 + else: + object_count: int = 0 + for predicted_object in prediction.annotations: + for label in predicted_object.labels: + if label.name in self.label_names: + object_count += 1 + return object_count + + def get_decision(self, score: float) -> bool: + """ + Make a decision based on a previously computed `score` and the threshold defined + for the trigger + + :param score: Float representing the score for a certain image, prediction pair + :return: Boolean indicating whether the trigger conditions are met (True), or + not (False) + """ + if self.mode == "lower": + return score < self.threshold + elif self.mode == "greater": + return score > self.threshold + elif self.mode == "equal": + return score == self.threshold diff --git a/geti_sdk/post_inference_hooks/utils.py b/geti_sdk/post_inference_hooks/utils.py new file mode 100644 index 00000000..1899e8b8 --- /dev/null +++ b/geti_sdk/post_inference_hooks/utils.py @@ -0,0 +1,63 @@ +# Copyright (C) 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. +"""Utility functions for the post inference hook module""" +import time +from threading import Lock + +try: + from collections.abc import Iterator +except ImportError: + # In python < 3.10 Iterator is in 'collections' + from collections import Iterator + + +class RateLimiter(Iterator): + """ + Iterator that yields at a maximum frequency of `frames_per_second`. + + :param frames_per_second: Maximum execution rate, defined in frames per second + :param is_blocking: Setting this to True will block execution until the next + yield. Setting this to False will cause the Iterator to yield `False` if it + is called before the next yield is available, and True otherwise + """ + + def __init__(self, frames_per_second: float = 1, is_blocking: bool = False) -> None: + self.interval = 1 / frames_per_second + self.is_blocking = is_blocking + self.__next_yield = 0 + self.__lock = Lock() + + def __iter__(self): + """ + Return the iterator + """ + return self + + def __next__(self) -> bool: + """ + Return `True` if called after the `self.interval` has elapsed with respect to + the last call. If `self.is_blocking == True`, will block execution otherwise, + until the interval has elapsed. If `self.is_blocking == False`, execution is + not blocked but `False` is returned instead. + """ + with self.__lock: + t = time.monotonic() + if t < self.__next_yield: + if self.is_blocking: + time.sleep(self.__next_yield - t) + t = time.monotonic() + else: + return False + self.__next_yield = t + self.interval + return True diff --git a/geti_sdk/utils/job_helpers.py b/geti_sdk/utils/job_helpers.py index 0b02921c..61239538 100644 --- a/geti_sdk/utils/job_helpers.py +++ b/geti_sdk/utils/job_helpers.py @@ -354,6 +354,11 @@ def monitor_job( inner_bar.set_description(previous_message) while monitoring and t_elapsed < timeout: job.update(session) + if job.total_steps > total_steps: + total_steps = job.total_steps + outer_bar.reset(total=job.total_steps) + outer_bar.update(job.current_step) + current_step = job.current_step if job.state in completed_states: outer_bar.update(total_steps - current_step) inner_bar.update(100 - previous_progress) diff --git a/notebooks/011_benchmarking_models.ipynb b/notebooks/011_benchmarking_models.ipynb index 697a7fff..197170fa 100644 --- a/notebooks/011_benchmarking_models.ipynb +++ b/notebooks/011_benchmarking_models.ipynb @@ -69,7 +69,7 @@ "metadata": {}, "outputs": [], "source": [ - "algorithms_to_benchmark = [\"MobileNetV2-ATSS\", \"SSD\", \"YOLOX\"]" + "algorithms_to_benchmark = [\"MobileNetV2-ATSS\", \"SSD\", \"YOLOX-S\"]" ] }, { @@ -282,7 +282,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.9.18" } }, "nbformat": 4, diff --git a/notebooks/012_post_inference_hooks.ipynb b/notebooks/012_post_inference_hooks.ipynb new file mode 100644 index 00000000..72f11079 --- /dev/null +++ b/notebooks/012_post_inference_hooks.ipynb @@ -0,0 +1,580 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a4c773be-4b40-4344-95e2-2fcbcb8d3119", + "metadata": {}, + "source": [ + "# Post inference hooks for inference model data collection\n", + "In this notebook we will have a look at how to set up post inference hooks for your inference models. The Geti SDK provides several basic triggers and actions that can be used to construct pipelines for, for instance, data collection, alerting, or other actions that need to take place based on inference results. \n", + "\n", + "These pipelines are referred to as `post inference hooks` and can be added to any `Deployment` for any project. In this notebook we will show how to configure them, and use them with existing deployments.\n", + "\n", + "To start off, we will create a post inference hook that implements the following behaviour:\n", + "\n", + "*For every inferred frame or image, check if the prediction contains any objects labelled `dog`. If it contains at least 1 dog, we want to collect it and send the image to the Geti server. The image will be stored in a new dataset called `Inferred images`, within the original project.*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a844097d-e4f8-4c99-ae85-a01c77f91395", + "metadata": {}, + "outputs": [], + "source": [ + "# As usual we will connect to the platform first, using the server details from the .env file\n", + "\n", + "from geti_sdk import Geti\n", + "from geti_sdk.utils import get_server_details_from_env\n", + "\n", + "geti_server_configuration = get_server_details_from_env()\n", + "\n", + "geti = Geti(server_config=geti_server_configuration)" + ] + }, + { + "cell_type": "markdown", + "id": "a8bf7d8d-d841-4f15-98f3-015c6306c708", + "metadata": {}, + "source": [ + "## Selecting a project\n", + "\n", + "we'll use the `COCO animal detection demo` project that we created in [notebook 002](002_create_project_from_dataset.ipynb)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1584f03e-4e35-4d24-9a43-e0bbdf0fb78a", + "metadata": {}, + "outputs": [], + "source": [ + "PROJECT_NAME = \"COCO animal detection demo\"\n", + "project = geti.get_project(PROJECT_NAME)" + ] + }, + { + "cell_type": "markdown", + "id": "c55f0489-af9a-4659-977f-391e1ccd1733", + "metadata": {}, + "source": [ + "## Create deployment for the project" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e2ae82f-bc66-4863-b423-82347737f810", + "metadata": {}, + "outputs": [], + "source": [ + "deployment = geti.deploy_project(PROJECT_NAME)" + ] + }, + { + "cell_type": "markdown", + "id": "0b4ffa71-fb63-4214-a308-898e9662934e", + "metadata": {}, + "source": [ + "## Checking deployment output\n", + "Let's quickly load the inference models and check the inference output on a sample image" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6d2788bc-fd8d-4363-85b0-cfcf00825ef7", + "metadata": {}, + "outputs": [], + "source": [ + "deployment.load_inference_models()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d26688a7-9e2d-4443-acb8-cd90798da662", + "metadata": {}, + "outputs": [], + "source": [ + "import cv2\n", + "\n", + "from geti_sdk.demos import EXAMPLE_IMAGE_PATH\n", + "from geti_sdk.utils import show_image_with_annotation_scene\n", + "\n", + "numpy_image = cv2.imread(EXAMPLE_IMAGE_PATH)\n", + "numpy_rgb = cv2.cvtColor(numpy_image, cv2.COLOR_BGR2RGB)\n", + "\n", + "prediction = deployment.infer(numpy_rgb)\n", + "\n", + "show_image_with_annotation_scene(numpy_rgb, prediction, show_in_notebook=True);" + ] + }, + { + "cell_type": "markdown", + "id": "983c3c09-06c4-4642-b4b2-394a3dcecdbf", + "metadata": {}, + "source": [ + "## Configuring a post inference hook to send image data to Geti\n", + "\n", + "With the deployment all set up and ready, let's go ahead and add a post inference hook! We will configure it to behave as follows:\n", + "\n", + "For each inferred image or frame:\n", + "\n", + "- If and only if the prediction contains at least one object labelled `dog`:\n", + "- Send the image to the Geti project, to a dedicated dataset named 'Inferred images'\n", + "\n", + "Basically, this behaviour can be separated into two parts: A **Trigger** and an **Action**. The first part, in which we check if the prediction contains at least one dog, is the Trigger. If the trigger activates, the Action will be carried out: Sending the data to the Intel Geti server. \n", + "\n", + "The reasoning here is that if the prediction contains a dog, we want to collect the image in our animal detection project so that we can include it in the next training round. To achieve this, we will use the `LabelTrigger`: It will activate if the prediction contains any objects labelled `dog`. \n", + "\n", + "Of course, many other triggers can be defined: For example, the `ObjectCountTrigger` can be used to activate only when a prediction contains a certain number of objects, the `EmptyLabelTrigger` will activate when the prediction does not contain any objects and the `ConfidenceTrigger` will activate when the probability for any of the predictions is below a certain threshold. \n", + "\n", + "The cell below shows how to define the hook outlined above. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "302568fe-0d1a-4333-863c-a99f2a94c9b9", + "metadata": {}, + "outputs": [], + "source": [ + "from geti_sdk.post_inference_hooks import (\n", + " GetiDataCollection,\n", + " LabelTrigger,\n", + " PostInferenceHook,\n", + ")\n", + "\n", + "trigger = LabelTrigger(\n", + " label_names=[\"dog\"]\n", + ") # the Trigger will activate whenever a prediction contains any object labelled `dog`\n", + "\n", + "action = GetiDataCollection( # the Action will send data to a new `Inferred images` dataset in the Geti project\n", + " session=geti.session,\n", + " workspace_id=geti.workspace_id,\n", + " project=project,\n", + " dataset=\"Inferred images\",\n", + " log_level=\"info\",\n", + ")\n", + "\n", + "hook = PostInferenceHook( # The Hook attaches the action to the trigger\n", + " trigger=trigger, action=action\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "576322e5-1440-412b-899e-6d8bfb8aa6e2", + "metadata": {}, + "source": [ + "Now, we just need to add the hook to the deployment" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "edaee43a-a8bc-49ee-a6e8-592a9efe940a", + "metadata": {}, + "outputs": [], + "source": [ + "deployment.add_post_inference_hook(hook)" + ] + }, + { + "cell_type": "markdown", + "id": "3a7354f6-57e3-48a1-bffa-123e07081fec", + "metadata": {}, + "source": [ + "Once added, whenever we run inference on an image or video frame, the hook will execute automatically." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c6f9b972-3411-4345-8951-5f2c9dbcf66c", + "metadata": {}, + "outputs": [], + "source": [ + "prediction = deployment.infer(numpy_rgb)\n", + "print(f\"Prediction contains objects with labels: {prediction.get_label_names()}\")" + ] + }, + { + "cell_type": "markdown", + "id": "47bcb165-d4e8-4210-b9b2-83b662ded568", + "metadata": {}, + "source": [ + "From the cell above, you should get a printout with the list of labels in the prediction. If the label `dog` is among them, you should also see a log line stating that the image was uploaded to the Geti project" + ] + }, + { + "cell_type": "markdown", + "id": "cf0740ef-de27-443d-8521-9b7aa70716fe", + "metadata": {}, + "source": [ + "## Adding multiple hooks\n", + "\n", + "We can add as many hooks as we like, each with different triggers and actions. Suppose we are primarily interested in images with dogs in them, for some reason. At the same time, we know that we are feeding our model images containing dogs, so any prediction that does not contain any dog-objects is suspicious. Those images might need to be added to the training set, in order to improve the model. So we want to sort the inferred images into a 'dogs' and a 'no dogs' category.\n", + "\n", + "In the next cell, we'll create two hooks to achieve both these goals and add them to the deployment.\n", + "The hooks we'll create are the following:\n", + "\n", + "**The 'dogs' hook**:\n", + "- Checks if the predictions contain 1 or more `dog`s. \n", + "- If so, then:\n", + "- Save the image, the prediction and the score that triggered the action to a folder `dogs` on disk. In this case, the score is the number of predicted dogs\n", + "\n", + "**The 'no dogs' hook**\n", + "- Checks if the predictions do not contain any dogs\n", + "- If so, send the image to the Geti server, to a separate dataset called `Inferred images - no dogs`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7be449fe-26a0-466b-92f7-78d4477ac255", + "metadata": {}, + "outputs": [], + "source": [ + "from geti_sdk.post_inference_hooks import FileSystemDataCollection, ObjectCountTrigger\n", + "\n", + "NUMBER_OF_THREADS_PER_HOOK = 10\n", + "\n", + "# First, remove any hooks that were added previously\n", + "deployment.clear_inference_hooks()\n", + "\n", + "# Create the 'dogs' trigger, action and hook\n", + "dogs_trigger = ObjectCountTrigger(\n", + " threshold=0, label_names=[\"dog\"], mode=\"greater\"\n", + ") # Trigger will activate whenever a prediction contains one or more objects labelled 'dog'\n", + "\n", + "dogs_action = FileSystemDataCollection(\n", + " target_folder=\"hook_data/dogs\",\n", + " file_name_prefix=\"image\",\n", + " save_predictions=True,\n", + " save_scores=True,\n", + " save_overlays=True,\n", + " log_level=\"debug\",\n", + ") # Action will store the image, prediction data, trigger score and the images with prediction overlays to the `dogs` folder on disk\n", + "\n", + "dogs_hook = PostInferenceHook(\n", + " trigger=dogs_trigger, action=dogs_action, max_threads=NUMBER_OF_THREADS_PER_HOOK\n", + ")\n", + "\n", + "# Create the 'no_dogs' trigger, action and hook\n", + "no_dogs_trigger = ObjectCountTrigger(\n", + " threshold=1, label_names=[\"dog\"], mode=\"lower\"\n", + ") # Trigger will activate whenever a prediction does not contain any objects labelled 'dog'\n", + "\n", + "no_dogs_action = GetiDataCollection( # the Action will send data to a new `Inferred images - no dogs` dataset in the Geti project\n", + " session=geti.session,\n", + " workspace_id=geti.workspace_id,\n", + " project=project,\n", + " dataset=\"Inferred images - no dogs\",\n", + ")\n", + "\n", + "no_dogs_hook = PostInferenceHook(\n", + " trigger=no_dogs_trigger,\n", + " action=no_dogs_action,\n", + " max_threads=NUMBER_OF_THREADS_PER_HOOK,\n", + ")\n", + "\n", + "# Add both hooks to the deployment\n", + "deployment.add_post_inference_hook(dogs_hook)\n", + "deployment.add_post_inference_hook(no_dogs_hook)" + ] + }, + { + "cell_type": "markdown", + "id": "2f5c7bb9-c95e-4ec7-9047-bc753c330e71", + "metadata": {}, + "source": [ + "Now that the hooks are created and added to the deployment, we can run the inference again.\n", + "\n", + "We will run it on 50 images from the COCO dataset. The images are selected such that each of them contains at least one dog. \n", + "\n", + "In the cell below, we first get a list of filepaths to images with `dog`s in them" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4065cb88-f208-45f4-bc8e-ee778e0a6b34", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "from geti_sdk.annotation_readers import DatumAnnotationReader\n", + "from geti_sdk.demos import get_coco_dataset\n", + "\n", + "n_images = 50\n", + "\n", + "path = get_coco_dataset()\n", + "ar = DatumAnnotationReader(path, annotation_format=\"coco\")\n", + "ar.filter_dataset(labels=[\"dog\"])\n", + "dog_image_filenames = ar.get_all_image_names()\n", + "dog_image_filepaths = [\n", + " os.path.join(path, \"images\", \"val2017\", fn + \".jpg\") for fn in dog_image_filenames\n", + "][0:n_images]\n", + "print(f\"Selected the first {n_images} images containing dogs from COCO dataset\")" + ] + }, + { + "cell_type": "markdown", + "id": "f07d88db-5c13-428d-b56a-0e0ad2d7e86e", + "metadata": {}, + "source": [ + "Now, we can run inference on the images and measure the time required in the cell below" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c4fa2040-09e8-40db-9278-558c03781e3d", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "\n", + "from tqdm import tqdm\n", + "\n", + "t_start = time.time()\n", + "for image_path in tqdm(dog_image_filepaths):\n", + " image = cv2.imread(image_path)\n", + " numpy_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n", + " deployment.infer(numpy_rgb)\n", + "t_elapsed = time.time() - t_start\n", + "print(\n", + " f\"Inference on {n_images} images with 2 post-inference hooks completed in {t_elapsed:.2f} seconds.\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "99a6136a-06c3-4233-8986-9ead9f69c43f", + "metadata": {}, + "source": [ + "You should now see a new folder `hook_data` in your working directory. Inside this folder, you'll find a folder titled `lots_of_dogs` and one named `no_dogs`. The `lots_of_dogs` folder contains four subfolders: `images`, `predictions`, `scores` and `overlays`. The contents of these folders are the following:\n", + "- `images` contains the image files which triggered the hook\n", + "- `predictions` contains the prediction data in .json format\n", + "- `scores` contains txt files with the score for each image that caused the hook to trigger\n", + "- `overlays` contains the images with the predictions visualized on top of them. This can be useful for checking the output visually.\n", + "\n", + "The file names are consistent across the subfolders, i.e. the prediction for a certain image can be found in the .json file with the same name, in the `predictions` folder.\n", + "\n", + "The `no_dogs` folder only contains `images` and `overlays`, because we configured the action with `save_predictions=False` and `save_scores=False`.\n", + "\n", + "If you take a look in those folders now, you'll find that they are populated with images, predictions, score files and overlay images." + ] + }, + { + "cell_type": "markdown", + "id": "b239dbae-8016-4385-b9b6-cb7e6e87b5ed", + "metadata": {}, + "source": [ + "### What about overhead?\n", + "\n", + "Because post inference hooks are executed in seperate threads, adding them to your deployment will add minimal overhead to the inference process. Let's clear the hooks and measure the inference time again, to get an estimate of the impact." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e8e5992a-984e-4ccc-84f8-441b150d467d", + "metadata": {}, + "outputs": [], + "source": [ + "# Remove any post-inference hooks\n", + "deployment.clear_inference_hooks()\n", + "\n", + "# Now run the inference loop without any hooks\n", + "t_start = time.time()\n", + "for image_path in tqdm(dog_image_filepaths):\n", + " image = cv2.imread(image_path)\n", + " numpy_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n", + " deployment.infer(numpy_rgb)\n", + "t_elapsed = time.time() - t_start\n", + "print(\n", + " f\"Inference on {n_images} images without post-inference hooks completed in {t_elapsed:.2f} seconds.\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "f06c9787-80d2-40c4-a88e-beb60f10629d", + "metadata": {}, + "source": [ + "Most likely you will notice that the inference time without any hooks is less than with the 2 hooks applied. Nevertheless, the additional time required is much smaller than if you would carry out the actions defined in the post-inference hooks after each inferred image in a synchronous manner." + ] + }, + { + "cell_type": "markdown", + "id": "077775ac-fbea-4191-8346-df5154961faa", + "metadata": {}, + "source": [ + "## Saving a deployment with post inference hooks\n", + "If you save a deployment with post inference hooks, the hook configuration will be saved with it. The cell below shows how to do this." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4054c0d3-c6e3-40cf-baf1-a698d2b040bb", + "metadata": {}, + "outputs": [], + "source": [ + "target_folder = os.path.join(\"deployments\", PROJECT_NAME)\n", + "deployment.save(target_folder);" + ] + }, + { + "cell_type": "markdown", + "id": "c07cb08c-77d1-4b37-a3b5-58fc3f1ef84b", + "metadata": {}, + "source": [ + "Once saved, the deployment can be recreated and the post inference hooks will be added automatically. Upon executing the cell below, you should see the two post inference hooks being added to the deployment." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f63c0e4-2805-4c5e-b7f6-9ef27d3699a8", + "metadata": {}, + "outputs": [], + "source": [ + "from geti_sdk.deployment import Deployment\n", + "\n", + "offline_deployment = Deployment.from_folder(target_folder)" + ] + }, + { + "cell_type": "markdown", + "id": "ee0bfcfd-6065-47ea-baf6-c85f12578ddf", + "metadata": {}, + "source": [ + "## Limiting hook execution rate\n", + "\n", + "Suppose that we are running inference on a video stream. In that case, we might get many sequential frames which activate a hook trigger, because frames that appear shortly after one another may look very similar. To avoid filling up our data collection folder with such near-duplicate frames, we can choose to limit the rate at which an action is allowed to run. This can be configured in the `PostInferenceHook`constructor, using the `limit_action_rate` and `max_frames_per_second` parameters.\n", + "\n", + "To give an example of this, in the last demo of this notebook we'll run inference 50 times *on the same image*, to simulate a video stream. We'll create a hook with the `AlwaysTrigger`, which activates after every inferred image or frame, and have it send the data to Geti using the `GetiDataCollection` action. However, to avoid filling up our dataset with 50 duplicate images, we'll limit the action execution rate to 1 frame per second.\n", + "\n", + "The cell below shows how to create this hook." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "381fa7c3-72ce-47c0-8039-239629e46ee1", + "metadata": {}, + "outputs": [], + "source": [ + "from geti_sdk.post_inference_hooks import AlwaysTrigger\n", + "\n", + "trigger = AlwaysTrigger()\n", + "action = GetiDataCollection(\n", + " session=geti.session,\n", + " workspace_id=geti.workspace_id,\n", + " project=project,\n", + " dataset=\"Inferred video frames\",\n", + " log_level=\"debug\",\n", + ")\n", + "geti_hook = PostInferenceHook(\n", + " trigger=trigger,\n", + " action=action,\n", + " max_threads=5,\n", + " limit_action_rate=True,\n", + " max_frames_per_second=1,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "18b239ff-e8a1-48b0-a256-ff6190f4a9af", + "metadata": {}, + "source": [ + "Let's first clear the existing hooks, and then add our new hook to the deployment" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "329cfc88-5fc2-4c3c-8e66-b6e85d14c608", + "metadata": {}, + "outputs": [], + "source": [ + "offline_deployment.clear_inference_hooks()\n", + "offline_deployment.add_post_inference_hook(geti_hook)\n", + "offline_deployment.load_inference_models()" + ] + }, + { + "cell_type": "markdown", + "id": "c14e6570-f67c-4b72-8d8d-e5b1031ecd3d", + "metadata": {}, + "source": [ + "Now, let's run inference 50 times again, each time on the same image" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c86d82f-c990-486f-981e-2b11347f255f", + "metadata": {}, + "outputs": [], + "source": [ + "image = cv2.imread(EXAMPLE_IMAGE_PATH)\n", + "numpy_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n", + "\n", + "t_start = time.time()\n", + "for ind in tqdm(range(50)):\n", + " offline_deployment.infer(numpy_rgb)\n", + "\n", + "t_elapsed = time.time() - t_start\n", + "print(\n", + " f\"50 inference iterations with rate-limited Geti I/O hook completed in {t_elapsed:.2f} seconds.\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "d523e182-ec0a-4f5e-bf0c-09e2ad08f378", + "metadata": {}, + "source": [ + "Your Geti project should now contain a new dataset called `Inferred video frames`, which should contain as many images as the number of seconds the benchmark took to run (plus one, because the action fires immediately on the first frame). So if it took 8 seconds to infer 50 times, the hook should have uploaded 9 images to Geti.\n", + "\n", + "Note that the trigger that we use is the `AlwaysTrigger`, which activates on every inferred image or video frame, regardless of the prediction outcome. The rate limiting happens in the `Action` phase of the hook, it ensures that the action does not run more frequently than allowed by the rate limit, even if the trigger fires much more often." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "852cf6f3-9765-4d61-ab5c-31e79bc7e73d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 9eee87cd..52c154b2 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -10,8 +10,8 @@ Pillow==10.3.* pathvalidate>=2.5.0 simplejson==3.19.* ipython==8.12.* -openvino>=2023.2.0,<2024.0.0 -openvino-model-api>=0.1.9 +openvino>=2023.2.0 +openvino-model-api==0.2.* certifi>=2022.12.7 joblib>=1.1.1 protobuf>=3.20.2 diff --git a/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_download_annotations_for_video.cassette b/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_download_annotations_for_video.cassette index 0b18bc03..7564b701 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_download_annotations_for_video.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_download_annotations_for_video.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6dc45bfe0c22aaf59563f8f64f3d84978e7bcc2ace6da84985c9717b93647bf4 -size 41250 +oid sha256:cb163792254995d4b87fe23073cc5e05787743a4cd5601f8240c27bcda1ca963 +size 41987 diff --git a/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_upload_and_retrieve_annotations_for_images.cassette b/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_upload_and_retrieve_annotations_for_images.cassette index 8511c32c..1de985c2 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_upload_and_retrieve_annotations_for_images.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_upload_and_retrieve_annotations_for_images.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2fa3a76b56442154da305ca29c7c73525df0ae1621812e875d70bb5a691b5f7d -size 304245 +oid sha256:2241238c505e49339fbff52b5163c0c0b24af8a19ba951375364560421f03a72 +size 307962 diff --git a/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_upload_and_retrieve_annotations_for_video.cassette b/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_upload_and_retrieve_annotations_for_video.cassette index ed591d4b..77bd70b3 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_upload_and_retrieve_annotations_for_video.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_upload_and_retrieve_annotations_for_video.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ecca3c742e2bb5d9614366574200b65d45f7f9fcfa450a5da70ca48fc1bb421a -size 3674239 +oid sha256:7da864a5d55a7dc6e868d4c2d9119f7f0871ecd97bba63ca554f7d6f4cdf7c99 +size 3718621 diff --git a/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_upload_and_retrieve_annotations_for_videos.cassette b/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_upload_and_retrieve_annotations_for_videos.cassette index 28cc52fa..d8a4207a 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_upload_and_retrieve_annotations_for_videos.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestAnnotationClient.test_upload_and_retrieve_annotations_for_videos.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e45c0af55b4a75ab37ad9f6ecdf021d6e17cb3b4042849a38021fc40d5846a7 -size 6245827 +oid sha256:193f756f6a15ecdce9331d7e0c6f18a51fb0b4d0accc60f530edc3b50fb360b8 +size 6321305 diff --git a/tests/fixtures/cassettes/DEVELOP/TestConfigurationClient.test_get_and_set_configuration.cassette b/tests/fixtures/cassettes/DEVELOP/TestConfigurationClient.test_get_and_set_configuration.cassette index ef29bc08..8ea38b74 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestConfigurationClient.test_get_and_set_configuration.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestConfigurationClient.test_get_and_set_configuration.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c82897c6ab3e57f4d9995d4cc6762a48805d6a58d8a4dbeb2fa3723deeea7b6 -size 106395 +oid sha256:9245740479736bbdb5f97797fa6155893dc26de8d24df8220f5a8eea189804c9 +size 110278 diff --git a/tests/fixtures/cassettes/DEVELOP/TestDatasetClient.test_create_dataset.cassette b/tests/fixtures/cassettes/DEVELOP/TestDatasetClient.test_create_dataset.cassette index 7922b550..f68c8c22 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestDatasetClient.test_create_dataset.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestDatasetClient.test_create_dataset.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da63b3bbde8c24e555b917ce1838ebdf6873d0db3e62f81b680c5957bdb1455c -size 13248 +oid sha256:cac976b0e5e20773bcf27b52f3c846a1b5b154482e7ffe8afaa5d26ac0f3460e +size 13478 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Classification project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Classification project].cassette index f4ba7837..31b454c4 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Classification project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Classification project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a15f2bb29fce614a7fbfe596cb94c713c280f41218feac475c0eb4881adababb -size 542695 +oid sha256:e8d4345f221cb9986c1b529d75c335d831f4beee60de2b16081bf4110aceed9c +size 553918 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Detection project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Detection project].cassette index 971e4936..b6f4a16c 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Detection project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Detection project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9a797dafb3193c3885708a61b3284c3e00f2936c75dfd54b038dda632131d50 -size 673051 +oid sha256:c7a80fed6f4b4c8cebf49e0207e9a62a32b335a275999fb8cb84b510a3c6dc10 +size 685735 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Instance segmentation project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Instance segmentation project].cassette index a7bdcfcc..2fca1e05 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Instance segmentation project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Instance segmentation project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7908b513ab6696366412729aa01943e3edcd2a6123cb05106a242d6a8e75fa52 -size 757895 +oid sha256:b69b1390c333f588e6a688ca955bf877311d28591ceb839ec3f0614f322f99e3 +size 771194 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Rotated detection project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Rotated detection project].cassette index 05755f55..20bb6db5 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Rotated detection project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Rotated detection project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3fbf8d21b33eb39e30c6bb32746bd7130de4bb79ca01e50913b13799e218eaf -size 677096 +oid sha256:abd689f4a6cbd44062a75c3f59ee52c7a732532d54e3946b468587ecb9923566 +size 689818 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Segmentation project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Segmentation project].cassette index 64e6999e..92a44418 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Segmentation project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_single_task_project_from_dataset[Segmentation project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3410fdc9dccfa715a0c9957c2f763fe580519e6ee935a044f47e746c4761d29 -size 745408 +oid sha256:e29e3b3d05ff41e7e542dc46143d36b6ad80d55fc8b0c4b2f67437638fcc9b26 +size 758612 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_task_chain_project_from_dataset[Detection to classification project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_task_chain_project_from_dataset[Detection to classification project].cassette index 853d9c69..d5396ec0 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_task_chain_project_from_dataset[Detection to classification project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_task_chain_project_from_dataset[Detection to classification project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7516f48c40c474f0f1e3802377f76b651a2d4c74ac41b440e705fbfcf611cf5 -size 864704 +oid sha256:d85873c1a1e1457c40ef508e92db8ef01406903adda0f8ba5742bd6313148c5c +size 879482 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_task_chain_project_from_dataset[Detection to segmentation project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_task_chain_project_from_dataset[Detection to segmentation project].cassette index dd0c7172..3b0799d0 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_task_chain_project_from_dataset[Detection to segmentation project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_create_task_chain_project_from_dataset[Detection to segmentation project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:baeb0569d8edb1a74d54d8ee7cfa837e14d54cab2431e7f4c11532472a66a410 -size 959837 +oid sha256:ed2875730bcd8d61ac7ffdee2a82ebe65b400f2b1b394d43521d42a9f0c9ed92 +size 975262 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_deployment[Single task project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_deployment[Single task project].cassette index 39f0a474..31a442a6 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_deployment[Single task project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_deployment[Single task project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0690b4b3566e061e94f5f05450565038655d58bb3f351e1e57ca8570baaede40 -size 11408720 +oid sha256:96dd06b5d77d8d6c63790a9a67ecd40fdd8cd7b81232548275f9a6a5576a3e44 +size 11552820 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_deployment[Task chain project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_deployment[Task chain project].cassette index 61dabf32..8329eac7 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_deployment[Task chain project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_deployment[Task chain project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b1717da76589f22bc3b844f441ef01589f0079b72db3e0232aac657df0ab614a -size 17949932 +oid sha256:2ebd9131b1f2705ff2d5d97759c82e613a4914413717188478c117b96d789a02 +size 18164278 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_download_and_upload_project[Single task project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_download_and_upload_project[Single task project].cassette index d1c2a198..f5f99787 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_download_and_upload_project[Single task project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_download_and_upload_project[Single task project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3f8e2bd1be4435563cc3e9908b143bc079e6018d11b207dd590868e8de48a5a -size 13194419 +oid sha256:676d85fdbbcc93172d46a97f95972359c81b78706ae682a139ddf621a68c367e +size 13362996 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_download_and_upload_project[Task chain project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_download_and_upload_project[Task chain project].cassette index cf3f320d..91a06ee9 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_download_and_upload_project[Task chain project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_download_and_upload_project[Task chain project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be7c1acb78b1a85a7af3a60d02bb2a740c8f5feef0d80963e58690b94cb6fe51 -size 2464113 +oid sha256:9821c5468dfcac9e1ee95a9fbe5a635a6551592240d9f3132b87190175a6c05a +size 2503752 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_download_project_including_models_and_predictions.cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_download_project_including_models_and_predictions.cassette index a9ae9ee7..0fdfecf4 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_download_project_including_models_and_predictions.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_download_project_including_models_and_predictions.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:265a941c3b87e2540ed7539f5a0bd5cf46c8c03e1b48a26b70629feb36cd0240 -size 155240640 +oid sha256:80c1709a394e60ba3910a960e5a4d976f5c90efb76600f05f71af186320e4f95 +size 157158893 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_post_inference_hooks.cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_post_inference_hooks.cassette new file mode 100644 index 00000000..06fc1d92 --- /dev/null +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_post_inference_hooks.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afaf700e2df57ed15c2f3d95803420cd8ce8a9b701d0956ec46990b687b48c4d +size 11462964 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_image[Single task project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_image[Single task project].cassette index b807e94e..02743354 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_image[Single task project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_image[Single task project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6feb6c09c8c4b75ab03ed20285207d8a61b2c798e7f43ae745d5e3c7a61db04e -size 119380 +oid sha256:9c17c5383208d233d9425f4b9669d2d104628a6df0c0f41fa4ee018c2e0f5d1b +size 123145 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_image[Task chain project].cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_image[Task chain project].cassette index fcef54bb..2e027d0e 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_image[Task chain project].cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_image[Task chain project].cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c88656a46e6569b442c49f192bc0ea5b1b23d60cc3f360c0168f7f3aea571b4 -size 214528 +oid sha256:934acbedcd2c2b731b5861aeee1a3c132399da005bae90aea0bc2e4978126f6a +size 216695 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_media_folder.cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_media_folder.cassette index d7a11848..eb4246ed 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_media_folder.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_media_folder.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b978ebec519c80afc05a253010296613e4ee4e782dc2ad7021085f8d4cf2f349 -size 6704671 +oid sha256:bef7ec13d610a9bf7ec07fc89134551ea7c755a1c2323cf0e1f7f1ca5c7fad84 +size 6790866 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_video.cassette b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_video.cassette index d1aefa76..77e74b4c 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_video.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGeti.test_upload_and_predict_video.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:381b60984d1a8f4d821a9c65b006ad781d783fe28a0b7f67a4c71cb753d1b4f4 -size 4057097 +oid sha256:4c7b29003544a896161076df6665083e8a4f25cc38cf186561681c9638802690 +size 4115764 diff --git a/tests/fixtures/cassettes/DEVELOP/TestGetiSession.test_logout.cassette b/tests/fixtures/cassettes/DEVELOP/TestGetiSession.test_logout.cassette index da0083c5..274353ae 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestGetiSession.test_logout.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestGetiSession.test_logout.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b956088f817d58e38e7bb7822808c54ad167459e5bf0091b01416f7b71588160 -size 28237 +oid sha256:7b94a45298e58ea2a6805f1603fc6eae8cce0943916030efc229b44add118c5a +size 28570 diff --git a/tests/fixtures/cassettes/DEVELOP/TestImageClient.test_upload_and_delete_image.cassette b/tests/fixtures/cassettes/DEVELOP/TestImageClient.test_upload_and_delete_image.cassette index 45c909b9..32122d80 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestImageClient.test_upload_and_delete_image.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestImageClient.test_upload_and_delete_image.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d416ee23e4fc59073c2f4c9383411be0f6dd45a8d3c59e583d4b300ab16f9682 -size 103439 +oid sha256:e68a0aabfebedb7a15c58945448edb5f53dea3a2ab45337facd7be0c13b396e9 +size 104731 diff --git a/tests/fixtures/cassettes/DEVELOP/TestImageClient.test_upload_image_folder_and_download.cassette b/tests/fixtures/cassettes/DEVELOP/TestImageClient.test_upload_image_folder_and_download.cassette index 93e59c49..8826abfe 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestImageClient.test_upload_image_folder_and_download.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestImageClient.test_upload_image_folder_and_download.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58c1b95f63afada0ce65a0101f21fde0342a11d371958f6353614cfdb1d8edc1 -size 1494792 +oid sha256:175d380cf54d07fff38c8c8edb522f8fa2b8033648af41a12fa9f1aaac5b4b5a +size 1512662 diff --git a/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_download_active_model_for_task.cassette b/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_download_active_model_for_task.cassette index 2a802f65..640c7e76 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_download_active_model_for_task.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_download_active_model_for_task.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:004afa4e766a1b3a6c04a114ca26c9f36ffa443847d794a1a345221edb017ae2 -size 133259331 +oid sha256:e64525205c00f8581cf3fcefa9a25e8f7a070d7217c95f6b855cbf6f2e6c3b71 +size 134827150 diff --git a/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_get_model_algorithm_task_and_version.cassette b/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_get_model_algorithm_task_and_version.cassette index 80efd0e5..c790f93c 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_get_model_algorithm_task_and_version.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_get_model_algorithm_task_and_version.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65efabed7110816cd523124f2197431aff610e8d472bc19c9a372f839b31fcb7 -size 33969 +oid sha256:9d0e1a382d74dea63f648f8e6e630e7ca472bf0b458b6d81423aeee621f7c160 +size 34341 diff --git a/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_get_model_group_by_algo_name.cassette b/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_get_model_group_by_algo_name.cassette index 2e76fc61..580dccbc 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_get_model_group_by_algo_name.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_get_model_group_by_algo_name.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1ee3faadc0942f707b2f0b13a15f256b825fbd9c9c8921746a59988aceddac6 -size 2832 +oid sha256:a0205939a0785f577469fa06a6218b1b7af246fb904ceb8982fb4f189abef58b +size 2878 diff --git a/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_predict_image.cassette b/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_predict_image.cassette index f4c30906..bea12c10 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_predict_image.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_predict_image.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2e1eb181ba929e9857e097b9fe29a321e40e2607e68b5307c308c4922184aef -size 1715122 +oid sha256:d2218d9ac4b9349e80df2824a467ae3f5fd075a4037e3c862b53341aa74308f0 +size 1735835 diff --git a/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_project_setup_and_get_model_by_job.cassette b/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_project_setup_and_get_model_by_job.cassette index 3fd52891..a0900f1c 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_project_setup_and_get_model_by_job.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_project_setup_and_get_model_by_job.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:866490c3e39484ddc5c9d6e68f0d0e367ec9062284ef95595b8b2d9c1adfa4cf -size 240375 +oid sha256:5c8e2c1335e7f942267bfa7965ae3352881541d73761afbc1a22f0a4931ddf9f +size 244115 diff --git a/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_set_active_model.cassette b/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_set_active_model.cassette index b4894be3..e9aa3d05 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_set_active_model.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestModelAndPredictionClient.test_set_active_model.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:18fa053abc643bbbcb9ab9db2e4993253ab77d43a8d52a653069e91f763e00c6 -size 345708 +oid sha256:73a23d22f6a04706d4a2e8edb9ed1ddc0b675277e82ba1916c7f8cf9ed2c3f59 +size 436697 diff --git a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_add_labels_multitask.cassette b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_add_labels_multitask.cassette index 7ea14cc5..0d20d9d7 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_add_labels_multitask.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_add_labels_multitask.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:32b5e61f5f26b3215010ebd3a63db682169c8f553fd60d9b4157bfef19ba7dfb -size 38611 +oid sha256:7fcc9161f988c335e779913d4912b4ca328ba9484d023a22fab2379a273a5e13 +size 27061 diff --git a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_add_labels_single_task.cassette b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_add_labels_single_task.cassette index 6d69bd32..34a908d6 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_add_labels_single_task.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_add_labels_single_task.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d456bd6129a4517bc86921af13df61ecefb1e84161b331b553d71c76f881827 -size 41295 +oid sha256:23f758ec42354ed7fdc96a2ab3520c0a776fabd73435acb0e2a078fe80254642 +size 29788 diff --git a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_create_and_delete_project.cassette b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_create_and_delete_project.cassette index 81a80ea2..150d94f9 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_create_and_delete_project.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_create_and_delete_project.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ada954cb487f0bc58bcf646770ec2a34c79e98d65c7905d9c78e5523a1258f8e -size 66497 +oid sha256:d5fedf66dda1e7db10906f6058fea2bfeefd0134f8e73f26e9f3be12dc9a29a1 +size 31254 diff --git a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.cassette b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.cassette index 90895b8b..03371eb7 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b93515f8d923596e4de26226af83ddb5ab7541f020de01d8409a26cac4d13b0 -size 96109 +oid sha256:223397b00100bc8cd8eb36b054068e3fc3cf52e34dcecf8d6b5504894d1df6ff +size 45964 diff --git a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.proj_A.cassette b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.proj_A.cassette index 35034b98..bed2f65c 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.proj_A.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.proj_A.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9adfa89d83cbc0d29cef9eaacc7a1236f70293a486abd3954cbdfa09b4c67936 -size 27746 +oid sha256:4f40394734f4e167560cda18aa7e4a4421c066bededc73efb93575754383fe8f +size 16068 diff --git a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.proj_B.cassette b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.proj_B.cassette index 64011948..48e62fc6 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.proj_B.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.proj_B.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6117507900a98cdefce176851734774e9bed47eba87a6d268ba4ffba89b62d39 -size 26477 +oid sha256:01be26ab8ed04f876ee02c3d903976b5ae1f9166d3a44f22daac09ac72fd209a +size 13511 diff --git a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.proj_C.cassette b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.proj_C.cassette index 2ffff506..f8419406 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.proj_C.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_get_all_projects.proj_C.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d257ae5fe82693725c8d67ec15010d95d7e93ab3598a58ebf39dea4a6259d73f -size 25208 +oid sha256:e865f33483e8929129d5a4598a482b9c9d1cc6e643f9ce27f34927c39c50cac4 +size 14794 diff --git a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_list_projects.cassette b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_list_projects.cassette index fd2a9e12..c069b74c 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_list_projects.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestProjectClient.test_list_projects.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b1f70e86a806e64cff714713f05b8138a991f4fd6e81d19363600903570e1abc -size 67067 +oid sha256:8908275a41bb9defa825adc3c68a2298a8e40c0686742c331e947366529cb63b +size 26651 diff --git a/tests/fixtures/cassettes/DEVELOP/TestTrainingClient.test_get_status.cassette b/tests/fixtures/cassettes/DEVELOP/TestTrainingClient.test_get_status.cassette index c7d57b39..403fff60 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestTrainingClient.test_get_status.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestTrainingClient.test_get_status.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a72482550d7bab373ab4e6828dda9b856085ea74f22d1a8b2b15a0d88df2477a -size 2860 +oid sha256:c445707c0e80294566d03f0fcee7e47343e0152d404b54f6466ceada9c3d60ee +size 2909 diff --git a/tests/fixtures/cassettes/DEVELOP/TestTrainingClient.test_train_task_and_get_jobs.cassette b/tests/fixtures/cassettes/DEVELOP/TestTrainingClient.test_train_task_and_get_jobs.cassette index d56694ce..48fe8d41 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestTrainingClient.test_train_task_and_get_jobs.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestTrainingClient.test_train_task_and_get_jobs.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57073ef91edeb92853396478d8e4cf0a2f49219e8ce9c6bcc1e0311eb690cad5 -size 25968 +oid sha256:b576a24d5a2c7038b6210060eb1bcb2a1178cfde4aea7f7b27f446f72c93b6cb +size 26398 diff --git a/tests/fixtures/cassettes/DEVELOP/TestUtils.test_get_supported_algorithms.cassette b/tests/fixtures/cassettes/DEVELOP/TestUtils.test_get_supported_algorithms.cassette index 5939ba13..052e4a50 100644 --- a/tests/fixtures/cassettes/DEVELOP/TestUtils.test_get_supported_algorithms.cassette +++ b/tests/fixtures/cassettes/DEVELOP/TestUtils.test_get_supported_algorithms.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:371d54002f914301b921e36057d00fae24e4508d420056aa73e8215b87b0d32e -size 5982 +oid sha256:16dab664ebc58050a7b6a0ef5bb9a56f910045cee704e611de06be6f0c484656 +size 6039 diff --git a/tests/fixtures/cassettes/DEVELOP/existing_projects.cassette b/tests/fixtures/cassettes/DEVELOP/existing_projects.cassette index c4faa910..82a475b3 100644 --- a/tests/fixtures/cassettes/DEVELOP/existing_projects.cassette +++ b/tests/fixtures/cassettes/DEVELOP/existing_projects.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86d15122a124156d6aafd5a71ee10f7b7b8827d0e7a4d6dd92afea0669234e01 -size 58732 +oid sha256:c9c312fb2de0c2e1b96a4c2792b71bb541f72ea80e6eb10d38bf028081b16671 +size 18243 diff --git a/tests/fixtures/cassettes/DEVELOP/geti.cassette b/tests/fixtures/cassettes/DEVELOP/geti.cassette index 8504f8ca..c400c692 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58094c3ddf83572296b2f5de20530c5f4227d9b376dd5aa4efa41147204c7710 -size 44514 +oid sha256:0c1e96a154a58998bf11fd44c684b45789c2b338703507c71561b48ae03b9ac2 +size 111051 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_annotation_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_annotation_client.cassette index b01814c0..2070809b 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_annotation_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_annotation_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9db6cbcac38063100113b39dce3163cd8acea3253fcff94cf846993a448fc2c8 -size 25305 +oid sha256:f39987ff7316e55d66af326e67774093d42316da53c0141842e00a5d1817c88a +size 13606 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_annotation_client_deletion.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_annotation_client_deletion.cassette index 647218b8..c0cac5d6 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_annotation_client_deletion.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_annotation_client_deletion.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0649454c5b67a53e08566fcb29df62ea4639f0eb860c130e69ec6d42974345e0 -size 25372 +oid sha256:d9c233009d849ab0ef6755d6af9490fd5d573a63d8d2f0d10dc858885f3633cf +size 13676 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_configuration_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_configuration_client.cassette index 3e1127f0..52f58bec 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_configuration_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_configuration_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b1b41b1942bf38f27fd8f3f3995415cb249b2db5fcdf154d41ac8872c3bb649f -size 25272 +oid sha256:e6f63f1cf178f7bfbfb8726b571c65b95adf8901fd03b9b3ffb7d0c1da844da3 +size 13575 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_configuration_client_configuration_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_configuration_client_configuration_client.cassette index fab9d3f5..169da624 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_configuration_client_configuration_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_configuration_client_configuration_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14ddf57c7fecddf295a12bd78ff51ea0a797697844720b42607695fd93123da8 -size 7440 +oid sha256:a4dd6b65e5741f5f41b0068f6bb0cd75a6bc7caffb8b3f7847ae610ebc4db739 +size 7540 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_configuration_client_deletion.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_configuration_client_deletion.cassette index c0afc2dd..06b720cd 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_configuration_client_deletion.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_configuration_client_deletion.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7bfd6c3020b62d5c023b7597fe6d7f7bddbf51b1d23ceeece18bff5c6eae149e -size 25702 +oid sha256:b2248cecddac66240abc6eabd93dc0ec10274a4ac961c2c159a3512c1bac255b +size 14010 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_dataset_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_dataset_client.cassette index 0e61dcb9..10acc646 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_dataset_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_dataset_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a807e3e9dbc2db95e6e86d3b33c60524d846e9492ca8be956e18c4dc516e5218 -size 25260 +oid sha256:3753b4181618f2f91351fda19f1f29459879c1473b6b88dee87302c9cbcc94d2 +size 13563 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_dataset_client_deletion.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_dataset_client_deletion.cassette index 60bf7161..d27c1587 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_dataset_client_deletion.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_dataset_client_deletion.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0391aa30c82f612eff6be385322deb0dca3dc89f5ddccc6999dc3c0d2ebcaadd -size 25956 +oid sha256:3be12a2c22b345e00e62f739175dc8d44032bde7b4eaa6bc4149a4328be01d38 +size 14264 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification.cassette index 2d9c2a33..8d390641 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14f227590cb1a75730a32cc73ecd0824cded4ee3e4660944bf548dcc64b4a271 -size 6592663 +oid sha256:87812e778c071088f5de4ffe6daa71d2417cde647916f4034e6acfb33910c653 +size 6674587 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_deletion.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_deletion.cassette index 728f2f12..71b480e2 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_deletion.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_deletion.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:295f6f95efb96e2a15ab6ebfd69bd8584295c25eaaf398602c083a048e65556d -size 13493 +oid sha256:ce531477b60b094f93c67892bebe980407117310f09eea66037c33d2dd3ce6c6 +size 16068 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_is_training.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_is_training.cassette index f9978815..67e9a092 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_is_training.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_is_training.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c4ebc5eec7438c4e1fe39798decab28e4a3b0db4f4cd3a18640ab49c0301b77 -size 2865 +oid sha256:d766e3fa249a0cca403819ec436b72fe407ae6623dd900e72a47f7b0e887bde9 +size 2914 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_setup_training.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_setup_training.cassette index 8fb7cf9b..ff989c60 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_setup_training.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_setup_training.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b97cf847616929d0f93ef786cbad02b4d559f27ff22d4a478769861632af821e -size 8135 +oid sha256:e1a8571fffc9fc640e0467f75e0fb072206418af3dec4921b90e083b7509082e +size 8277 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_training_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_training_client.cassette index 1120a877..b27ca042 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_training_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_classification_training_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f7ece0056ad0f231d28aca2ad032668434c438038a1d609d18f155750c5ab4f -size 3803 +oid sha256:3a501bc53e625cc490019cc31d59186e52c546e09ed74b9f05ccb1d37fd78fbf +size 3853 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification.cassette index 19ffe4e2..107e4796 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:afd491da9dfb693d428638316050d6cd3c34daa3e56c6e2229f803db5a295439 -size 13671 +oid sha256:1719673a1f3620e8aef68c49cbed351f0468244def8cf129e1675cc5fb69654f +size 16181 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_add_annotated_media.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_add_annotated_media.cassette index ce6f2c8b..a06eb38b 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_add_annotated_media.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_add_annotated_media.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe26b381f2bf6c873767207dfbfd14bf1fbe7b8cd910efa235fb79a64c3985ff -size 729005 +oid sha256:7402efa9b7511fe9d42a5a089dcb52957fc616b7cca5f395ca22f8c8f6604827 +size 737925 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_configuration_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_configuration_client.cassette index 9ac5ab7c..74b3c63b 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_configuration_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_configuration_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b34136b47fd8fd214f5db0dd99f0e7aa87f8dc1041274d4ff0cb458e94f62277 -size 9270 +oid sha256:49778c6e2bf395d3a733e1ca95c8bfb27aaaa900f4218c9a80a6091f96681489 +size 9375 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_deletion.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_deletion.cassette index 54df85d3..677ecdb1 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_deletion.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_deletion.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db872628589f6270210a11e1cafa498609db88a0f02b48140fc205f6be38715c -size 13193 +oid sha256:788fb06315f2938397f85ed8f9148eee15f4f4028bbc24ba5c6777b73a7e1f96 +size 15632 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_is_training.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_is_training.cassette index 225026a1..5dd25245 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_is_training.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_is_training.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a102ba15a4e7338bdeacdc5ccffdc6dfe3876c5f81aac1e21c5fe245d855703 -size 3124 +oid sha256:6b81ae1c4be8e79aaba2d56e82ef6d2bb9501d6cf39613b8bcd92eec79843be8 +size 3175 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_set_auto_train.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_set_auto_train.cassette index 3e9179d9..0a218873 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_set_auto_train.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_set_auto_train.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1fea746d371948bbba2f8b234a561be86fba0a5d4ab4eae8785f286164f6e1a -size 47338 +oid sha256:26e43eb6c96938a4542b8c94ef9f5e8d07c3b276708d7e87b87fee177b4b2246 +size 47765 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_set_minimal_hypers.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_set_minimal_hypers.cassette index 2fd90540..5467fc7c 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_set_minimal_hypers.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_set_minimal_hypers.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:148af19c6b9de6fd07278dd875e938206e4c9618af3cdaf8f0dbb433830aa0dd -size 295541 +oid sha256:4d396784873c79203aec6d48259dd9d52a3c02bdd7eccd9c22a7f0b4aa227df0 +size 298005 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_setup_training.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_setup_training.cassette index 24817ed3..e4f4070c 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_setup_training.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_setup_training.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97f6021f1760a692d5aaf6d2c79ef6e2e57a85647c1aa7f5d2b2f0e46e88522c -size 16890 +oid sha256:cca54cb3225ded29b3ca0671a1f2d7239e321b869c886fde3a499383791edb1b +size 17173 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_training_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_training_client.cassette index cb5f1947..e2bea4c5 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_training_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_geti_detection_to_classification_training_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2e884dfc2082cc7715b2d3fd135363f75b2ea847ee100e5fcfaabc744f0d516 -size 5982 +oid sha256:361e2df2288a7c158760dd7bfb9926039c01f7ee306cd6b03c3e9e7d510b20da +size 6039 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_image_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_image_client.cassette index 1035a845..ef7c6cae 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_image_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_image_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f906c724c9362b5a71167a417fd6f0c54e4dd21e9ca68db7475c5381368ab0cb -size 11133 +oid sha256:c3ea56dca9caa402bb5a98fdda1029961b9b51449ee9044d785302baf89c2a16 +size 13559 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_image_client_deletion.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_image_client_deletion.cassette index d9984235..262a60ed 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_image_client_deletion.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_image_client_deletion.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d708aa93c3c00ff5322f0025660657ccbb4a8a726e934e8f095619b9f670121 -size 11563 +oid sha256:b9f404a0d76b248d51303291adb5e48daf44dcb53534c08424a2f436430581a1 +size 13994 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client.cassette index 6ce1551a..621fd6ae 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1242c5f759c704d944aa6e70b6b488a65e07b85b50bcefc0ec403715e1a123bb -size 11223 +oid sha256:6d3de4e8be9e019ba10863143b5b3e2cfca49e79746066675b06112565503c32 +size 13647 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_add_annotated_media.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_add_annotated_media.cassette index 42c98713..4f5f226d 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_add_annotated_media.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_add_annotated_media.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf36c951b0b39e1ee625623d2cdf48e14741982608df21d679c61831de9c84a7 -size 465250 +oid sha256:950880928c613a1e4d28db1977159f7a5d0d104a215f9e8f88571d635881f9ca +size 471108 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_configuration_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_configuration_client.cassette index dda8a68b..3e0dc6e0 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_configuration_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_configuration_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68b58c19703315e20202dee0187f69bd947feb2c46d24ba3da6f2c13cc9db846 -size 6831 +oid sha256:55234a214a17f89e5d622675e28ff63f47411066261fd6e184f0273b5cee9498 +size 6928 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_deletion.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_deletion.cassette index b10b69d3..441e210f 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_deletion.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_deletion.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f8b0c3df57cfe0ebdde70f1cafa98c38b15ebf5b12ba3a194407adb35c3ec3c3 -size 11349 +oid sha256:132a5e5cd11cff7ca6aebbac36de446676cee7f0e548785dfb778208e2f61d0c +size 13780 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_model_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_model_client.cassette index b571741d..8a000c87 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_model_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_model_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:59078aad90d8348e95a94747333c29262dc8a5eda4c5e37a2174f2734f4ee120 -size 3803 +oid sha256:1c80d252ca0da1ab350c8130261975a25d21e73d14af7d0379a0a40ded1490e0 +size 3853 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_prediction_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_prediction_client.cassette index 29116602..0e8f166c 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_prediction_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_prediction_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:af4d6b12a1b182ca84056536a3475f65a77dbee1220a9c443808fed93aec65d5 -size 2370 +oid sha256:d0c85aebc8871caf074748a1f91e4c939fa8aff4b8731cabb131c5a0bbc22714 +size 2414 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_set_auto_train.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_set_auto_train.cassette index 31369f1e..b13ddb55 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_set_auto_train.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_set_auto_train.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1db2fb0a56a6b4185873a261c179be8010aad202a9b23f0d462d74cecf287bfa -size 20988 +oid sha256:9b0b1bf847dba8ac133d72c8a454cb5ce80358a35f03d17b05740438ce00bfdc +size 21186 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_set_minimal_hypers.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_set_minimal_hypers.cassette index 7e7d0432..4836a0c7 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_set_minimal_hypers.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_set_minimal_hypers.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f1ab8247df6b1e83daf104ccdc850e2be305b49fa4bd9030b73e72598ef8f51 -size 88335 +oid sha256:53611a9398994ca1791d25c19bef7169a8c6abbec33949c3bc834c6b7cbb0e84 +size 89121 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_training_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_training_client.cassette index 8fa9694a..607ec452 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_training_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_model_and_prediction_client_training_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a846f3c8286a470778fdde9b11d17c8353dda2a01eb02546ee8b87ee010b98a -size 3803 +oid sha256:c9bb56a1e6392e4e09552721f188b3f61fc41726c585068fcd7866ce1781bdd3 +size 3853 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_project_hierarchical.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_project_hierarchical.cassette index 79d0df32..36955acf 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_project_hierarchical.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_project_hierarchical.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04319b17950a36846d26b87e091ae8bf8737fa3e519fcfed461a3427d6e8f430 -size 28517 +oid sha256:0928de39cdae0192240ec12feb35fb418b29445794db2a5f63176125c489156b +size 16832 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_project_hierarchical_deletion.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_project_hierarchical_deletion.cassette index d6dbf64f..e83f030b 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_project_hierarchical_deletion.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_project_hierarchical_deletion.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:359142415419ac69076ce76ac181e7c7faaf6b639d7a28303490b1c26ee6363f -size 28946 +oid sha256:70231c67f6095967f4fb44e15089c60c98a5a3bb8c367f2dbbc7c2612d895b3c +size 17264 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_project_simple.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_project_simple.cassette index a925b9f5..6e1f7e86 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_project_simple.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_project_simple.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d1932075713275a6d917456921e9860bd2d4633293173e3e299833982fa6bbb -size 25320 +oid sha256:518d8b6f0dd0eced99d99ba05f11535d0836bfcfd1eac69ac952f776d981aeae +size 13621 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_test_supported_algos.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_test_supported_algos.cassette index cacf9ac8..4aeab5ba 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_test_supported_algos.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_test_supported_algos.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d895bbe9f67340224adf688cda5c926f5e15eb80f89c63d522605863b34de3d3 -size 26652 +oid sha256:a2e0e44b306f67032c990228a717460ff2ca827c3488f9e46f095956c3f56e58 +size 14962 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_test_supported_algos_deletion.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_test_supported_algos_deletion.cassette index 3495bd74..09578d66 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_test_supported_algos_deletion.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_test_supported_algos_deletion.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7c508964859a6a31f129aa6b2224d42993e1d712c935fb92eb845319ac106bf -size 26996 +oid sha256:475ed42b1b2ecf2640d767923c1898bedcbba558f0c2fd6b2b06841668f72f6a +size 15310 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client.cassette index 1899b0f2..7069bd16 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:98800cb64a2f96b0929af9a380f6d803d14e200bba4769a5237182838d616070 -size 25262 +oid sha256:fc189727859123d05f86a24df5c531d540ba9d4040e7fb4e1a7c9db941047a23 +size 13565 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_add_annotated_media.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_add_annotated_media.cassette index 3e34c525..278bccee 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_add_annotated_media.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_add_annotated_media.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:974d7fbecc6c136c9e0604c418be846329b123317d1df5afde928565768e4dd8 -size 583993 +oid sha256:c268789d0c68758168cfd3d34dda23fa14a766b937cec53dd6c267a680ac3492 +size 591223 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_configuration_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_configuration_client.cassette index e52591c6..dbee34b5 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_configuration_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_configuration_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a889ace90cb9cd89fc45839b82cd5b4b03591c2a60f5110ba7d8bd8f44c0185 -size 7440 +oid sha256:c728fb9336cc776d94bf426db0c8b484770c1fe9d035b1d6d78e1a3ad91e749d +size 7540 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_deletion.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_deletion.cassette index 8621f37f..23b2139a 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_deletion.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_deletion.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:216d1e07043be4cb25e41c9d7657c43a3ddd9fa54f5dfa37a772e812bad5f408 -size 25692 +oid sha256:c08eb7279483b9a46875e40758a4351cd46f071b39e59f3b8b4a075cce20aad7 +size 14000 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_set_auto_train.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_set_auto_train.cassette index 40c23c39..b6fc5674 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_set_auto_train.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_set_auto_train.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb4caed78c0437e8e6204324794bf0216441a1815f51d8532703d48e92ff2ac9 -size 25669 +oid sha256:296e9964671497b1be09e368af17e26b6a96b082218ec9c9bc769d2a3739fed4 +size 26606 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_set_minimal_hypers.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_set_minimal_hypers.cassette index f8284ffe..ce984720 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_set_minimal_hypers.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_set_minimal_hypers.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b263e2087267420e9c474ae59fd3705cd7a9a757e706dca21babd2ac3b20ccc6 -size 109227 +oid sha256:d2659d9607a6c8a658b3c37cc6020d09861eb27ce6adebd8b87fdc22582ac6a7 +size 113162 diff --git a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_training_client.cassette b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_training_client.cassette index 44098d51..6d6ac3d6 100644 --- a/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_training_client.cassette +++ b/tests/fixtures/cassettes/DEVELOP/geti_sdk_test_training_client_training_client.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:25a9521797d639d95bc75dfab49b031ec38f83a5a37f2f461497eb63f6515157 -size 4602 +oid sha256:6cfc644d14c9525c6cdcd105e7823eb642c5e4d3e03f576fa2e66a1054feaf21 +size 4655 diff --git a/tests/fixtures/cassettes/DEVELOP/session.cassette b/tests/fixtures/cassettes/DEVELOP/session.cassette index b18bd491..e1c8bd64 100644 --- a/tests/fixtures/cassettes/DEVELOP/session.cassette +++ b/tests/fixtures/cassettes/DEVELOP/session.cassette @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:451fa0c072ba3b837f791d605683c44ce77346ca44da7adb48380201214a9c74 -size 70114 +oid sha256:953cf239dab60f0d7daf183ea1c28ec6c33033d55cba0a70db515fabd39567fb +size 71088 diff --git a/tests/fixtures/cassettes/LEGACY/TestAnnotationClient.test_download_annotations_for_video.cassette b/tests/fixtures/cassettes/LEGACY/TestAnnotationClient.test_download_annotations_for_video.cassette new file mode 100644 index 00000000..f86bac3b --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestAnnotationClient.test_download_annotations_for_video.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2e7535f6e250c4bc6c55ca86e58ccbeb1cd2c3339f903a2331399dce731be28f +size 41987 diff --git a/tests/fixtures/cassettes/LEGACY/TestAnnotationClient.test_upload_and_retrieve_annotations_for_images.cassette b/tests/fixtures/cassettes/LEGACY/TestAnnotationClient.test_upload_and_retrieve_annotations_for_images.cassette new file mode 100644 index 00000000..b49d6aa7 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestAnnotationClient.test_upload_and_retrieve_annotations_for_images.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2799a5cc1709b670e07fff957135c7ed912688e749bd3c33520bdc9afcdfeb68 +size 307962 diff --git a/tests/fixtures/cassettes/LEGACY/TestAnnotationClient.test_upload_and_retrieve_annotations_for_video.cassette b/tests/fixtures/cassettes/LEGACY/TestAnnotationClient.test_upload_and_retrieve_annotations_for_video.cassette new file mode 100644 index 00000000..e86752a7 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestAnnotationClient.test_upload_and_retrieve_annotations_for_video.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8aba27e1e1d866a7137ae87f0b94454dbab4dc39ed9948e3edaf45968ef36e2d +size 3718621 diff --git a/tests/fixtures/cassettes/LEGACY/TestAnnotationClient.test_upload_and_retrieve_annotations_for_videos.cassette b/tests/fixtures/cassettes/LEGACY/TestAnnotationClient.test_upload_and_retrieve_annotations_for_videos.cassette new file mode 100644 index 00000000..f73f8688 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestAnnotationClient.test_upload_and_retrieve_annotations_for_videos.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2e9b06fb10625deda1cb1b3b8127318c013f748b7c79f1947911139939677a0 +size 6321305 diff --git a/tests/fixtures/cassettes/LEGACY/TestConfigurationClient.test_get_and_set_configuration.cassette b/tests/fixtures/cassettes/LEGACY/TestConfigurationClient.test_get_and_set_configuration.cassette new file mode 100644 index 00000000..89eea2f8 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestConfigurationClient.test_get_and_set_configuration.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:06b115c64e3e76a6c3bd948ca47a77ffa1a5c4bec8e7701cdbd8e952edef1082 +size 110278 diff --git a/tests/fixtures/cassettes/LEGACY/TestDatasetClient.test_create_dataset.cassette b/tests/fixtures/cassettes/LEGACY/TestDatasetClient.test_create_dataset.cassette new file mode 100644 index 00000000..451fe2d9 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestDatasetClient.test_create_dataset.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d14033eac684307f30837f1e243c2bd5c8a7e61ba472f2562e34e69beb8b503c +size 13478 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Classification project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Classification project].cassette new file mode 100644 index 00000000..5d6b7e76 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Classification project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:517cd8a569ab9ab2098971e831529731b7fb237f2e333e05cba1822ef092b300 +size 549362 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Detection project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Detection project].cassette new file mode 100644 index 00000000..0d18e27b --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Detection project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be89877acebbc25bafce4a18b0afd6bf7ddf4ad3252be0b0c49bee9173bd7077 +size 681179 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Instance segmentation project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Instance segmentation project].cassette new file mode 100644 index 00000000..78028c88 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Instance segmentation project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:68ca9f4ce1cd506cacef070401763c0faf33d6d74710d720e8cddccc919dff60 +size 766638 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Rotated detection project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Rotated detection project].cassette new file mode 100644 index 00000000..8cae4dd9 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Rotated detection project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0298fab69dc0b0d7d5c8b1bf7001e3902bc0fdb08a1d8bb7da3859b80bbd3c56 +size 685295 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Segmentation project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Segmentation project].cassette new file mode 100644 index 00000000..e2c00eec --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_single_task_project_from_dataset[Segmentation project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ab59ef4216c28764de97f2862d4dc8192735cd85d89f6064e7437b1b94071a0 +size 754056 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_task_chain_project_from_dataset[Detection to classification project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_task_chain_project_from_dataset[Detection to classification project].cassette new file mode 100644 index 00000000..7e2506ba --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_task_chain_project_from_dataset[Detection to classification project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c51cc2bfed15da8e457f64ce6aa3b9a37884f7202cde5c7f49dfb4980630531 +size 874926 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_task_chain_project_from_dataset[Detection to segmentation project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_task_chain_project_from_dataset[Detection to segmentation project].cassette new file mode 100644 index 00000000..4def0189 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_create_task_chain_project_from_dataset[Detection to segmentation project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b1212b5f470ccdc321fc0583ecf442c6d82d9c3ece7614be3f4a271e948e4b +size 970706 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_deployment[Single task project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_deployment[Single task project].cassette new file mode 100644 index 00000000..7a07a913 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_deployment[Single task project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:38260e3e7ec1031ed5b1e5ae232cd562026e1f9200509fb555a63ca8a0d96ca4 +size 11548082 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_deployment[Task chain project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_deployment[Task chain project].cassette new file mode 100644 index 00000000..4f5398b7 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_deployment[Task chain project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b53553fde8208f0f9d2ecc16ee18667361c792a3d5cdc6457dcb4fc562c9765f +size 18160941 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_download_and_upload_project[Single task project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_download_and_upload_project[Single task project].cassette new file mode 100644 index 00000000..09a42966 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_download_and_upload_project[Single task project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d3c9126bffa1f78d214f98488ce24c7e2f2ce7bab502f8e31e29ec8be85a0cf +size 13351606 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_download_and_upload_project[Task chain project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_download_and_upload_project[Task chain project].cassette new file mode 100644 index 00000000..773b8875 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_download_and_upload_project[Task chain project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a60be5754996e9019ba0c036850c15ff8751fc5e23fcf5bdfa30e428633161bf +size 2492369 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_download_project_including_models_and_predictions.cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_download_project_including_models_and_predictions.cassette new file mode 100644 index 00000000..f63dc92f --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_download_project_including_models_and_predictions.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f2fdb6a5526b367ae9c47eaeb7d9a013e8da60971931d25d3d82f0e813c2f38 +size 157151781 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_post_inference_hooks.cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_post_inference_hooks.cassette new file mode 100644 index 00000000..e97c549c --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_post_inference_hooks.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da601a10c1988864fd4d483f389746617ff5b7184b08b93425f01de83aef3ad5 +size 11460505 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_upload_and_predict_image[Single task project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_upload_and_predict_image[Single task project].cassette new file mode 100644 index 00000000..d1833eb0 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_upload_and_predict_image[Single task project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3cce0cb4254b373dbc016884a30d47b1bd5e6e4dacc02233ffbaf278f3c7f281 +size 120867 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_upload_and_predict_image[Task chain project].cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_upload_and_predict_image[Task chain project].cassette new file mode 100644 index 00000000..194bd31f --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_upload_and_predict_image[Task chain project].cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4473647f8d126abf039e1cfd91c191e950b5ade7d6faa0295b2772791062b7d0 +size 217565 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_upload_and_predict_media_folder.cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_upload_and_predict_media_folder.cassette new file mode 100644 index 00000000..7c9ee745 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_upload_and_predict_media_folder.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad8fcd8c6da25e670eabd95056383408b68a74db9d3e984bd9af60472867a27d +size 6786314 diff --git a/tests/fixtures/cassettes/LEGACY/TestGeti.test_upload_and_predict_video.cassette b/tests/fixtures/cassettes/LEGACY/TestGeti.test_upload_and_predict_video.cassette new file mode 100644 index 00000000..9f37de16 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGeti.test_upload_and_predict_video.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b5297aac79a9f20a92f62cf22c0002922feb40f46fd21a96f059ca4c738496e +size 4106642 diff --git a/tests/fixtures/cassettes/LEGACY/TestGetiSession.test_logout.cassette b/tests/fixtures/cassettes/LEGACY/TestGetiSession.test_logout.cassette new file mode 100644 index 00000000..61327fac --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestGetiSession.test_logout.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6da30814d4f38ea6b12a13eccf25beb322ecc467daacffaef921e487ea70cdb7 +size 28570 diff --git a/tests/fixtures/cassettes/LEGACY/TestImageClient.test_upload_and_delete_image.cassette b/tests/fixtures/cassettes/LEGACY/TestImageClient.test_upload_and_delete_image.cassette new file mode 100644 index 00000000..a79c76de --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestImageClient.test_upload_and_delete_image.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd39f49a0211645321693e22f0db3632f4f3a38d6f6aa6d5e83d14a69bf10710 +size 104731 diff --git a/tests/fixtures/cassettes/LEGACY/TestImageClient.test_upload_image_folder_and_download.cassette b/tests/fixtures/cassettes/LEGACY/TestImageClient.test_upload_image_folder_and_download.cassette new file mode 100644 index 00000000..945b714f --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestImageClient.test_upload_image_folder_and_download.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8662fc9bccda3d739e9d70e938db5658351f178c880927a2cdfd9cfe5890ea1d +size 1512662 diff --git a/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_download_active_model_for_task.cassette b/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_download_active_model_for_task.cassette new file mode 100644 index 00000000..247472de --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_download_active_model_for_task.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f912d199d0dd08f4c23453c5c9ed550007a5d8bee6a6ba544a0d2ccd06f680f +size 134827052 diff --git a/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_get_model_algorithm_task_and_version.cassette b/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_get_model_algorithm_task_and_version.cassette new file mode 100644 index 00000000..023aba48 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_get_model_algorithm_task_and_version.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89b242df044b51dca15a844b89c6454da8d373ec49a1f29de21008961aefa384 +size 34341 diff --git a/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_get_model_group_by_algo_name.cassette b/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_get_model_group_by_algo_name.cassette new file mode 100644 index 00000000..c142464d --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_get_model_group_by_algo_name.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f195a82d78e990776f0d5dcbbb36cf49414f3bc0572af6aba835246010fe39b +size 2878 diff --git a/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_predict_image.cassette b/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_predict_image.cassette new file mode 100644 index 00000000..a1ebbe33 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_predict_image.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:56148127a2731368fb75e10a060e08629edeffaa369e293f00e84e61153e51e8 +size 1735835 diff --git a/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_project_setup_and_get_model_by_job.cassette b/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_project_setup_and_get_model_by_job.cassette new file mode 100644 index 00000000..e071c205 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_project_setup_and_get_model_by_job.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b1a2147bd625a98823afe7fa1d552bc882160fe954a18ccafdc5d46ee3d1b54e +size 229330 diff --git a/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_set_active_model.cassette b/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_set_active_model.cassette new file mode 100644 index 00000000..cd201f20 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestModelAndPredictionClient.test_set_active_model.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb7414c7d4da96948450ab2f557bdb88a1054ae1ac22fd4582df938086cf7c1d +size 321360 diff --git a/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_add_labels_multitask.cassette b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_add_labels_multitask.cassette new file mode 100644 index 00000000..b380363a --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_add_labels_multitask.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ec1e7179448a547989271b82098710ca89a0bfca8da16154c1ee5059722c87c +size 24783 diff --git a/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_add_labels_single_task.cassette b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_add_labels_single_task.cassette new file mode 100644 index 00000000..3ff83aa5 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_add_labels_single_task.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8fb4330343d86f82bdd11892ccce78047cf5281bd14b7a11c9e375bdaeea83e +size 27510 diff --git a/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_create_and_delete_project.cassette b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_create_and_delete_project.cassette new file mode 100644 index 00000000..4ea1063d --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_create_and_delete_project.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0055e1fc3b8f48b4ddca0acafae8042d1b1fd9ce9d3f26098e68fc658d2f6f8d +size 24429 diff --git a/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_get_all_projects.cassette b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_get_all_projects.cassette new file mode 100644 index 00000000..fac7b0e3 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_get_all_projects.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb75884da864b9658ae0e2306ced28b65b687a95497f3e3e4ff91cc18d55d32d +size 33368 diff --git a/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_get_all_projects.proj_A.cassette b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_get_all_projects.proj_A.cassette new file mode 100644 index 00000000..7cb30547 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_get_all_projects.proj_A.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f215640a6adcc3f6b2ab87439393b0241c920fed03b8417b339bde0f79fafaac +size 11242 diff --git a/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_get_all_projects.proj_B.cassette b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_get_all_projects.proj_B.cassette new file mode 100644 index 00000000..11474b9d --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_get_all_projects.proj_B.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:73ab5782327401a02e75601bcc4e683f567858422cc2d8ee068dd4e7d49d0125 +size 12516 diff --git a/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_get_all_projects.proj_C.cassette b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_get_all_projects.proj_C.cassette new file mode 100644 index 00000000..40c6c760 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_get_all_projects.proj_C.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ac51d848c3202e4dd1855f68997e53e528d5d90a4ccff9dd0e01ac057438ad0 +size 13790 diff --git a/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_list_projects.cassette b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_list_projects.cassette new file mode 100644 index 00000000..fe2c8a25 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestProjectClient.test_list_projects.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:967adbc773338688a7fa59e0be42b214832e2cbc8eceb654a19d04a62a6027c1 +size 16599 diff --git a/tests/fixtures/cassettes/LEGACY/TestTrainingClient.test_get_status.cassette b/tests/fixtures/cassettes/LEGACY/TestTrainingClient.test_get_status.cassette new file mode 100644 index 00000000..1b9b325e --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestTrainingClient.test_get_status.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:253890399cc86d0a322533019cdc3241862f8c7092b05f94a99f8959d93de1e3 +size 2909 diff --git a/tests/fixtures/cassettes/LEGACY/TestTrainingClient.test_train_task_and_get_jobs.cassette b/tests/fixtures/cassettes/LEGACY/TestTrainingClient.test_train_task_and_get_jobs.cassette new file mode 100644 index 00000000..cd7f7563 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestTrainingClient.test_train_task_and_get_jobs.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d531c481ff57e0b00be241bbd750167435fe0a7cbd68686db506c943af9766f +size 26398 diff --git a/tests/fixtures/cassettes/LEGACY/TestUtils.test_get_supported_algorithms.cassette b/tests/fixtures/cassettes/LEGACY/TestUtils.test_get_supported_algorithms.cassette new file mode 100644 index 00000000..819ca022 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/TestUtils.test_get_supported_algorithms.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:736a3e111d004dc77b2bb244ddbd86b06fac2a22907e6ecc5669260ed3484f07 +size 6039 diff --git a/tests/fixtures/cassettes/LEGACY/existing_projects.cassette b/tests/fixtures/cassettes/LEGACY/existing_projects.cassette new file mode 100644 index 00000000..7d7fedc9 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/existing_projects.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:498e872150dc3bb873a3c92bca03c9e98ad6a1f772fd369e9ac31e4465bd903f +size 8200 diff --git a/tests/fixtures/cassettes/LEGACY/geti.cassette b/tests/fixtures/cassettes/LEGACY/geti.cassette new file mode 100644 index 00000000..d4c6c8a9 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c5d8ac7a4e6835c65ac27bc7793736ec31e21101112c9970cbfce84a194df8d +size 111050 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_annotation_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_annotation_client.cassette new file mode 100644 index 00000000..e2798680 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_annotation_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ae5f5432995829cf50dda521099fa3dd17693fc70cbb7c40f464418eaf4edb3 +size 11337 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_annotation_client_deletion.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_annotation_client_deletion.cassette new file mode 100644 index 00000000..5c01a8fd --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_annotation_client_deletion.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4dc80e4fc7749922869342ab62f423c8b29255688c0775fad40a9e236c9eaad8 +size 11398 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_configuration_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_configuration_client.cassette new file mode 100644 index 00000000..72933141 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_configuration_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:19489458a41ff6a1996bb0a13b68cb57a8de3ef7e19d6651f7af5779669d2757 +size 11306 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_configuration_client_configuration_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_configuration_client_configuration_client.cassette new file mode 100644 index 00000000..33f118db --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_configuration_client_configuration_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:230bffb5f63f6cf97c9a64de32606ee8dcccdb98b8a91a7e678f9527ba49fdad +size 7540 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_configuration_client_deletion.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_configuration_client_deletion.cassette new file mode 100644 index 00000000..b60acbbb --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_configuration_client_deletion.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ecd97fe05ed5fa526b9775abf5a6f4160dbecd3074d2f470720370edd3d0019 +size 11732 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_dataset_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_dataset_client.cassette new file mode 100644 index 00000000..6366b515 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_dataset_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8fb926931e6abd400eff7838a05eb1862bc60c59c0ea308c7e1b02b9ffbde1e +size 11294 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_dataset_client_deletion.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_dataset_client_deletion.cassette new file mode 100644 index 00000000..4f37d8cd --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_dataset_client_deletion.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91cd345529a45acd4efb0655431a8a61ca230c252836dc8ca0968899074212ac +size 11986 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification.cassette new file mode 100644 index 00000000..41bff5cb --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f460fdc3ccff1acc874df90d7e1e59224f1a7ac35c02720f670acae126588caa +size 6672318 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification_deletion.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification_deletion.cassette new file mode 100644 index 00000000..034f344b --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification_deletion.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:189f3e0fd898e87ea8492e841dd408886e8cdbbf132aa508b4f7b2a370e0668b +size 13789 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification_is_training.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification_is_training.cassette new file mode 100644 index 00000000..aa804b6e --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification_is_training.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67717ccb577ab00a6ee4513b82ca6d39fed11f48eda52cfa3a1393b453cd1b3b +size 2914 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification_setup_training.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification_setup_training.cassette new file mode 100644 index 00000000..97d133a4 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification_setup_training.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd89179a8d374f0fbcd8b0b163cdf2e269eecce4a3bc104a6a5e5bc59a009d61 +size 8277 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification_training_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification_training_client.cassette new file mode 100644 index 00000000..98170b40 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_classification_training_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:10f23a8f878b4cefecf94fd1dea62c2143c24944f155be70bb258fd65825ed9b +size 3853 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification.cassette new file mode 100644 index 00000000..51ce88db --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:decb426d7f48db7bd323244eea115a8c611f2af07d0fa56efd885021ddfe9aca +size 13903 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_add_annotated_media.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_add_annotated_media.cassette new file mode 100644 index 00000000..97c31444 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_add_annotated_media.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1eb9187f99de8fae1a61339cf0a6178f98d8b67c616c4d8acb1a9a94f2fbcbf5 +size 737932 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_configuration_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_configuration_client.cassette new file mode 100644 index 00000000..b2261ce0 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_configuration_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:70aa472e1b0547c9e336b0669ca72b1d08d8ad6da1458848a65fc79447dd8f28 +size 9375 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_deletion.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_deletion.cassette new file mode 100644 index 00000000..3e8ab718 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_deletion.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a23851076bfb13665886d38068c27f93c305a997462c16c404f9ec9aa435194 +size 13352 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_is_training.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_is_training.cassette new file mode 100644 index 00000000..89203e02 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_is_training.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51c801139c36983cb17c6955a398667979ac497e40c78b8c70ceb4887669b4a2 +size 3175 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_set_auto_train.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_set_auto_train.cassette new file mode 100644 index 00000000..e522e73a --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_set_auto_train.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2e527b72f89a66d3c79164b9e8d59395891b04c9946ae336d3b1753d586711d2 +size 47765 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_set_minimal_hypers.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_set_minimal_hypers.cassette new file mode 100644 index 00000000..2facfb94 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_set_minimal_hypers.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4a70db614ec02f9564170e6adcfa37046debde9f72a6a7b0f4e6b345283631b +size 298005 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_setup_training.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_setup_training.cassette new file mode 100644 index 00000000..986d9a99 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_setup_training.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:088622f430f53e9400ea84f92254632c0a565e270a6a043f913139c6af833136 +size 17173 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_training_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_training_client.cassette new file mode 100644 index 00000000..540d8a7d --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_geti_detection_to_classification_training_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13420c698b399f052433d7ae18ec79fc32725749ac3ad58eb356c03dd6c3fdc6 +size 6039 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_image_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_image_client.cassette new file mode 100644 index 00000000..9c8c7422 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_image_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9499ce89e425ca1a5fda352d6385ef05f2aa30e4b40443e0bdfa7a25558b0d02 +size 11290 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_image_client_deletion.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_image_client_deletion.cassette new file mode 100644 index 00000000..daf2c6bd --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_image_client_deletion.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97db40e18fd8a28e10e37bccb0f8f21d2ecef02f6e1beda36692afe40b08a396 +size 11716 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client.cassette new file mode 100644 index 00000000..9061eaf3 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5157485d3122d934c3677686f2ddc5b67b1f9a3aa0f6f103aadc3e5fa9585f9e +size 11378 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_add_annotated_media.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_add_annotated_media.cassette new file mode 100644 index 00000000..779a266c --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_add_annotated_media.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09dfa9e78903b712c11d523ddc798d23b0fe61857350dadc970c43dc12b63b37 +size 471108 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_configuration_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_configuration_client.cassette new file mode 100644 index 00000000..4ac9e2e1 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_configuration_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:595f6253a613ca73ae90bcf4bd873ef94c86bfb8fbab2090c874d554f251c64e +size 6928 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_deletion.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_deletion.cassette new file mode 100644 index 00000000..51c94866 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_deletion.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb9f89a0bdc14309c7d778c6dbd5f65ed42e03e0d64d8f36b67b7854e9ffeb52 +size 11502 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_model_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_model_client.cassette new file mode 100644 index 00000000..fa42d0a1 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_model_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91b30adc4537dd98c86fa469cce7510568be10691155cc17f02a1e4de9c276ad +size 3853 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_prediction_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_prediction_client.cassette new file mode 100644 index 00000000..03063360 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_prediction_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0738260e2ae434f59b0cee045bbbb6074b773c02078bdca928fc676efd39db84 +size 2414 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_set_auto_train.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_set_auto_train.cassette new file mode 100644 index 00000000..e891efa4 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_set_auto_train.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:534008678a203e7ea0cc85f25f40e07aa4cea482153a693c9fc61982bd5fd5bd +size 21186 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_set_minimal_hypers.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_set_minimal_hypers.cassette new file mode 100644 index 00000000..57cb0c9c --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_set_minimal_hypers.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b882db0fb661e4382fe94dd4b5a0c0cb3fc7c306d41dfea4e90aa17fec16d8ba +size 89121 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_training_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_training_client.cassette new file mode 100644 index 00000000..01591ec7 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_model_and_prediction_client_training_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7308db103adcbabc25bd7f27a1d4cca8fb8b9a3fe84acc4762a3602e17847f2f +size 3853 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_project_hierarchical.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_project_hierarchical.cassette new file mode 100644 index 00000000..6046098c --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_project_hierarchical.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1799e66fbd708292337d5fa121cdba9f83ec844018ee7f4c6961ff8c59ca8bb +size 14563 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_project_hierarchical_deletion.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_project_hierarchical_deletion.cassette new file mode 100644 index 00000000..88754610 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_project_hierarchical_deletion.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2591adb7fd01a596143ec3577d28fc5efe3a2b9b3cf216d0be4c9730168bdb27 +size 14986 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_project_simple.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_project_simple.cassette new file mode 100644 index 00000000..5a60df64 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_project_simple.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0e995e4215814f71d8975164c073d8da727d5170e678477f3344b0b4b226a136 +size 11352 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_test_supported_algos.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_test_supported_algos.cassette new file mode 100644 index 00000000..27dfb69d --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_test_supported_algos.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:821d2f68c4594c2a9d691d4af954c2926fe1ba3dda990dfc94590aa5ae85f365 +size 12693 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_test_supported_algos_deletion.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_test_supported_algos_deletion.cassette new file mode 100644 index 00000000..96ab6edd --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_test_supported_algos_deletion.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:45d228d0a58dfbdf83edc3cf9b544e080b7c4348f09322e44ab95ff3bfd863fa +size 13032 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client.cassette new file mode 100644 index 00000000..dd4c1acb --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:438c2f2c5e3c0ff7bd8acefa6eba30d24a2bec3ae1e916b785f14ba35a2a51d7 +size 11296 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_add_annotated_media.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_add_annotated_media.cassette new file mode 100644 index 00000000..53b6e4fa --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_add_annotated_media.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ccd2eca5a587a7c759e6eaf8b5707776202bbb07db00819d13576167bb9356c6 +size 591237 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_configuration_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_configuration_client.cassette new file mode 100644 index 00000000..0f3ae5d1 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_configuration_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:485670dd350cc17fa9218f9baf641566865488f1d443dffc39bdb10a9887ca74 +size 7540 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_deletion.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_deletion.cassette new file mode 100644 index 00000000..4e3c5944 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_deletion.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:497e8b727da3e247b3669ec4d3911d074931d180ec5134a5e7d5cad4cec4e474 +size 11722 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_set_auto_train.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_set_auto_train.cassette new file mode 100644 index 00000000..1fdf1e22 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_set_auto_train.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f441d009b14d7a7c1df02e4aefc30185e8a6e96a9e63f84ec2b312c62d5359ce +size 26606 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_set_minimal_hypers.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_set_minimal_hypers.cassette new file mode 100644 index 00000000..cd7852c1 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_set_minimal_hypers.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d42bcb5e04f61792ccbf85a3532be52981a9a8f8169b0fe07cfd9aa4d5a37ca8 +size 113162 diff --git a/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_training_client.cassette b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_training_client.cassette new file mode 100644 index 00000000..5405d132 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/geti_sdk_test_training_client_training_client.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d12aa899f9ef78a48de0e1cc5400bea5d15787c51671b49602beb3f768dbedf +size 4655 diff --git a/tests/fixtures/cassettes/LEGACY/session.cassette b/tests/fixtures/cassettes/LEGACY/session.cassette new file mode 100644 index 00000000..b2bdfd92 --- /dev/null +++ b/tests/fixtures/cassettes/LEGACY/session.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9943ca931b9ec14128a58c63940838e6dc67da35f6852df9beefd3a746b11f31 +size 71083 diff --git a/tests/fixtures/cassettes/TestGeti.test_post_inference_hooks.cassette b/tests/fixtures/cassettes/TestGeti.test_post_inference_hooks.cassette new file mode 100644 index 00000000..57b220bc --- /dev/null +++ b/tests/fixtures/cassettes/TestGeti.test_post_inference_hooks.cassette @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a5d6a60598d87a84741e4a3c1e6146ae1099af2213d0391a7a42434b8d723fba +size 11461104 diff --git a/tests/pre-merge/integration/rest_clients/test_annotation_client.py b/tests/pre-merge/integration/rest_clients/test_annotation_client.py index 03d13f12..aac2d5df 100644 --- a/tests/pre-merge/integration/rest_clients/test_annotation_client.py +++ b/tests/pre-merge/integration/rest_clients/test_annotation_client.py @@ -201,7 +201,7 @@ def test_upload_and_retrieve_annotations_for_videos( annotation_client.upload_annotations_for_videos(videos=[video_1, video_2]) if fxt_test_mode != SdkTestMode.OFFLINE: - time.sleep(5) + time.sleep(10) # Fetch annotations from annotation client annotation_scenes_for_video_1 = ( diff --git a/tests/pre-merge/integration/test_geti.py b/tests/pre-merge/integration/test_geti.py index 8eb88985..9967b6dd 100644 --- a/tests/pre-merge/integration/test_geti.py +++ b/tests/pre-merge/integration/test_geti.py @@ -26,6 +26,13 @@ from geti_sdk.data_models import Job, Prediction, Project from geti_sdk.deployment import Deployment from geti_sdk.http_session import GetiRequestException +from geti_sdk.post_inference_hooks import ( + AlwaysTrigger, + ConfidenceTrigger, + FileSystemDataCollection, + GetiDataCollection, + PostInferenceHook, +) from geti_sdk.rest_clients import ( AnnotationClient, DatasetClient, @@ -542,6 +549,67 @@ def test_deployment( ) assert deployment_from_folder.models[0].name == deployment.models[0].name + @pytest.mark.vcr() + def test_post_inference_hooks( + self, + fxt_project_service: ProjectService, + fxt_geti: Geti, + fxt_image_path: str, + fxt_temp_directory: str, + ): + """ + Test that adding post inference hooks to a deployment works, and that the + hooks function as expected + """ + project = fxt_project_service.project + deployment_folder = os.path.join(fxt_temp_directory, project.name) + + deployment = fxt_geti.deploy_project(project.name) + dataset_name = "Test hooks" + + # Add a GetiDataCollectionHook + trigger = AlwaysTrigger() + action = GetiDataCollection( + session=fxt_geti.session, + workspace_id=fxt_geti.workspace_id, + project=project, + dataset=dataset_name, + ) + hook = PostInferenceHook(trigger=trigger, action=action) + deployment.add_post_inference_hook(hook) + + # Add a FileSystemDataCollection hook + hook_data = os.path.join(deployment_folder, "hook_data") + trigger_2 = ConfidenceTrigger(threshold=1.1) + action_2 = FileSystemDataCollection(target_folder=hook_data) + hook_2 = PostInferenceHook(trigger=trigger_2, action=action_2, max_threads=0) + deployment.add_post_inference_hook(hook_2) + + deployment.load_inference_models(device="CPU") + image_bgr = cv2.imread(fxt_image_path) + image_np = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB) + _ = deployment.infer(image_np) + + dataset_client = DatasetClient( + session=fxt_geti.session, + workspace_id=fxt_geti.workspace_id, + project=project, + ) + + assert len(deployment.post_inference_hooks) == 2 + + # Assert that the hooks have fired + dataset = dataset_client.get_dataset_by_name(dataset_name) + hook_images = fxt_project_service.image_client.get_all_images(dataset=dataset) + assert len(hook_images) == 1 + expected_folders = ["images", "overlays", "predictions", "scores"] + for folder_name in expected_folders: + assert folder_name in os.listdir(hook_data) + assert len(os.listdir(os.path.join(hook_data, folder_name))) == 1 + + deployment.clear_inference_hooks() + assert len(deployment.post_inference_hooks) == 0 + @pytest.mark.vcr() def test_download_project_including_models_and_predictions( self, diff --git a/tests/pre-merge/unit/deployment/test_prediction_converter.py b/tests/pre-merge/unit/deployment/test_prediction_converter.py index 1707e6fc..5cbf0c35 100644 --- a/tests/pre-merge/unit/deployment/test_prediction_converter.py +++ b/tests/pre-merge/unit/deployment/test_prediction_converter.py @@ -15,7 +15,7 @@ import numpy as np import pytest -from openvino.model_api.models.utils import ( +from model_api.models.utils import ( AnomalyResult, ClassificationResult, Detection,