diff --git a/.doc_gen/cross-content/scenario_LookoutVisionCreateTrainStartModel_Python_block.xml b/.doc_gen/cross-content/scenario_LookoutVisionCreateTrainStartModel_Python_block.xml
deleted file mode 100644
index d3f205798b8..00000000000
--- a/.doc_gen/cross-content/scenario_LookoutVisionCreateTrainStartModel_Python_block.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- %phrases-shared;
-]>
-
-
- Creates and optionally starts an &LYRAlong; model using command line arguments.
- The example code creates a new project, training dataset, optional test dataset,
- and model. After model training is completed, you can use a provided script to
- try your model with an image.
-
-
- This example requires a set of images to train its model. You can find example
- circuit board images on GitHub that you can use for training and testing.
- For details on how to copy these images to an &S3long; (&S3;) bucket, see
- Prepare example images.
-
-
- For complete source code and instructions on how to set up and run, see the full example on
- GitHub.
-
-
diff --git a/.doc_gen/metadata/lookoutvision_metadata.yaml b/.doc_gen/metadata/lookoutvision_metadata.yaml
deleted file mode 100644
index 5500e5c196f..00000000000
--- a/.doc_gen/metadata/lookoutvision_metadata.yaml
+++ /dev/null
@@ -1,333 +0,0 @@
-# zexi 0.4.3
-lookoutvision_CreateDataset:
- guide_topic:
- title: Creating your dataset
- url: lookout-for-vision/latest/developer-guide/model-create-dataset.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Datasets
- - python.example_code.lookoutvision.CreateDataset
- services:
- lookoutvision: {CreateDataset}
-lookoutvision_Scenario_CreateManifestFile:
- title: Create a &LYRA; manifest file using an &AWS; SDK
- title_abbrev: Create a manifest file
- synopsis: create a &LYRA; manifest file and upload it to &S3;.
- category: Scenarios
- guide_topic:
- title: Creating a manifest file
- url: lookout-for-vision/latest/developer-guide/manifest-files.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Datasets
- - python.example_code.lookoutvision.Scenario_CreateManifestFile
- services:
- lookoutvision: {}
-lookoutvision_DeleteDataset:
- guide_topic:
- title: Deleting a dataset
- url: lookout-for-vision/latest/developer-guide/delete-dataset.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Datasets
- - python.example_code.lookoutvision.DeleteDataset
- services:
- lookoutvision: {DeleteDataset}
-lookoutvision_DescribeDataset:
- guide_topic:
- title: Viewing your dataset
- url: lookout-for-vision/latest/developer-guide/view-datasets.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Datasets
- - python.example_code.lookoutvision.DescribeDataset
- services:
- lookoutvision: {DescribeDataset}
-lookoutvision_Scenario_FindTagInProjects:
- title: Find a &LYRA; project with a specific tag using an &AWS; SDK
- title_abbrev: Find a project with a specific tag
- synopsis: find a &LYRA; project with a specific tag.
- category: Scenarios
- guide_topic:
- title: Tagging models
- url: lookout-for-vision/latest/developer-guide/tagging-model.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Scenario_FindTagInProjects
- services:
- lookoutvision: {}
-lookoutvision_Scenario_ExportDatasets:
- title: Export the datasets from a &LYRA; project using an &AWS; SDK
- title_abbrev: Export the datasets from a project
- synopsis: export the datasets from a &LYRA; project.
- category: Scenarios
- guide_topic:
- title: Exporting datasets from a project (SDK)
- url: lookout-for-vision/latest/developer-guide/export-dataset-sdk.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Scenario_ExportDatasets
- services:
- lookoutvision: {}
-lookoutvision_StartModel:
- guide_topic:
- title: Starting your model
- url: lookout-for-vision/latest/developer-guide/run-start-model.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Hosting
- - python.example_code.lookoutvision.StartModel
- services:
- lookoutvision: {StartModel}
-lookoutvision_StopModel:
- guide_topic:
- title: Stopping your model
- url: lookout-for-vision/latest/developer-guide/run-stop-model.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Hosting
- - python.example_code.lookoutvision.StopModel
- services:
- lookoutvision: {StopModel}
-lookoutvision_Scenario_ListHostedModels:
- title: List &LYRA; models that are currently hosted using an &AWS; SDK
- title_abbrev: List models that are currently hosted
- synopsis: list &LYRA; models that are currently hosted.
- category: Scenarios
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Hosting
- - python.example_code.lookoutvision.Scenario_ListHostedModels
- services:
- lookoutvision: {}
-lookoutvision_DetectAnomalies:
- guide_topic:
- title: Detecting anomalies in an image
- url: lookout-for-vision/latest/developer-guide/inference-detect-anomalies.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.DetectAnomalies
- services:
- lookoutvision: {DetectAnomalies}
-lookoutvision_CreateModel:
- guide_topic:
- title: Training your model
- url: lookout-for-vision/latest/developer-guide/model-train.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Models
- - python.example_code.lookoutvision.CreateModel
- services:
- lookoutvision: {CreateModel}
-lookoutvision_DescribeModel:
- guide_topic:
- title: Viewing your models
- url: lookout-for-vision/latest/developer-guide/view-models.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Models
- - python.example_code.lookoutvision.DescribeModel
- services:
- lookoutvision: {DescribeModel}
-lookoutvision_ListModels:
- guide_topic:
- title: Viewing your models
- url: lookout-for-vision/latest/developer-guide/view-models.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Models
- - python.example_code.lookoutvision.ListModels
- services:
- lookoutvision: {ListModels}
-lookoutvision_DeleteModel:
- guide_topic:
- title: Deleting a model
- url: lookout-for-vision/latest/developer-guide/delete-model.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Models
- - python.example_code.lookoutvision.DeleteModel
- services:
- lookoutvision: {DeleteModel}
-lookoutvision_CreateProject:
- guide_topic:
- title: Creating your project
- url: lookout-for-vision/latest/developer-guide/model-create-project.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Projects
- - python.example_code.lookoutvision.CreateProject
- services:
- lookoutvision: {CreateProject}
-lookoutvision_DeleteProject:
- guide_topic:
- title: Deleting a project
- url: lookout-for-vision/latest/developer-guide/delete-project.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Projects
- - python.example_code.lookoutvision.DeleteProject
- services:
- lookoutvision: {DeleteProject}
-lookoutvision_ListProjects:
- guide_topic:
- title: Viewing your projects
- url: lookout-for-vision/latest/developer-guide/view-projects.html
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Projects
- - python.example_code.lookoutvision.ListProjects
- services:
- lookoutvision: {ListProjects}
-
-lookoutvision_Hello:
- title: Hello &LYRA;
- title_abbrev: Hello &LYRA;
- synopsis: get started using &LYRA;.
- category: Hello
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- sdkguide:
- excerpts:
- - description:
- snippet_tags:
- - python.example_code.lookoutvision.Hello
- services:
- lookoutvision: {ListProjects}
-
-
-lookoutvision_Scenario_CreateTrainStartModel:
- title: Create, train, and start a &LYRA; model using an &AWS; SDK
- title_abbrev: Create, train, and start a model
- synopsis: create, train, and start a &LYRA; model.
- category: Scenarios
- languages:
- Python:
- versions:
- - sdk_version: 3
- github: python/example_code/lookoutvision
- block_content: scenario_LookoutVisionCreateTrainStartModel_Python_block.xml
- services:
- lookoutvision: {}
diff --git a/python/example_code/lookoutvision/README.md b/python/example_code/lookoutvision/README.md
deleted file mode 100644
index 2f71ad19978..00000000000
--- a/python/example_code/lookoutvision/README.md
+++ /dev/null
@@ -1,340 +0,0 @@
-# Lookout for Vision code examples for the SDK for Python
-
-## Overview
-
-Shows how to use the AWS SDK for Python (Boto3) to work with Amazon Lookout for Vision.
-
-
-
-
-_Lookout for Vision enables you to find visual defects in industrial products, accurately and at scale._
-
-## ⚠ Important
-
-* Running this code might result in charges to your AWS account. For more details, see [AWS Pricing](https://aws.amazon.com/pricing/) and [Free Tier](https://aws.amazon.com/free/).
-* Running the tests might result in charges to your AWS account.
-* We recommend that you grant your code least privilege. At most, grant only the minimum permissions required to perform the task. For more information, see [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege).
-* This code is not tested in every AWS Region. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).
-
-
-
-
-## Code examples
-
-### Prerequisites
-
-For prerequisites, see the [README](../../README.md#Prerequisites) in the `python` folder.
-
-Install the packages required by these examples by running the following in a virtual environment:
-
-```
-python -m pip install -r requirements.txt
-```
-
-
-
-
-### Get started
-
-- [Hello Lookout for Vision](hello.py#L4) (`ListProjects`)
-
-
-### Single actions
-
-Code excerpts that show you how to call individual service functions.
-
-- [CreateDataset](datasets.py#L32)
-- [CreateModel](models.py#L29)
-- [CreateProject](projects.py#L31)
-- [DeleteDataset](datasets.py#L201)
-- [DeleteModel](models.py#L167)
-- [DeleteProject](projects.py#L54)
-- [DescribeDataset](datasets.py#L227)
-- [DescribeModel](models.py#L102)
-- [DetectAnomalies](inference.py#L23)
-- [ListModels](models.py#L143)
-- [ListProjects](projects.py#L73)
-- [StartModel](hosting.py#L30)
-- [StopModel](hosting.py#L87)
-
-### Scenarios
-
-Code examples that show you how to accomplish a specific task by calling multiple
-functions within the same service.
-
-- [Create a manifest file](datasets.py)
-- [Create, train, and start a model](../../example_code/lookoutvision)
-- [Export the datasets from a project](export_datasets.py)
-- [Find a project with a specific tag](find_tag.py)
-- [List models that are currently hosted](hosting.py)
-
-
-
-
-
-## Run the examples
-
-### Instructions
-
-
-
-There are three demonstrations in this set of examples:
-
-* Create and host a model.
-* Detect anomalies in images using a model.
-* Find tags attached to a model.
-
-Before running these demonstrations do the following:
-- Follow the [setup instructions](https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/su-set-up.html).
-- Read [Getting started with the SDK](https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/getting-started-sdk.html).
-- Create an Amazon S3 bucket in your AWS account. You'll use the bucket to store your
- training images, manifest files, and training output.
-- Copy your training and test images to your S3 bucket. To try this code with example
- images, You can use the example [circuit board dataset](https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/su-prepare-example-images.html).
-
-The folder structures for the training and test images must be as follows:
-```
-s3://amzn-s3-demo-bucket//
- normal/
- anomaly/
-```
-`train` and `test` can be any folder path.
-Place normal images in the `normal` folder. Anomalous images in the `anomaly` folder.
-
-##### Example structure
-
-The example contains the following files.
-
-###### datasets.py
-
-A class that shows how to create and manage datasets. Also shows how to create a
-manifest file based on images found in an Amazon S3 bucket. Used by `train_host.py`.
-
-Manifest files are used to create training and test datasets. `train_host.py` uses
-`datasets.py` to create training and (optionally) test manifest files, and upload them
-to an Amazon S3 bucket location that you specify. For more information about manifest
-files, see [Creating a dataset using an Amazon SageMaker Ground Truth manifest file](https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/create-dataset-ground-truth.html).
-
-###### find_tag.py
-
-Shows how to find a tag attached to a Lookout for Vision model.
-
-###### hello.py
-
-Confirms that you can call Amazon Lookout for Vision operations.
-If you haven't previously created a project in the current AWS Region,
-the response is an empty list, however it confirms that you can call the
-Lookout for Vision API.
-
-###### hosting.py
-
-A class that shows how to start and stop a Lookout for Vision project. Also shows how
-to list hosted models. Used by `train_host.py`.
-
-###### inference.py
-
-A class that shows how to analyze an image (JPEG/PNG) with a hosted Lookout for Vision
-model. You can also analyze an image stored in an Amazon S3 bucket.
-The example shows how you can classify images as normal or anomalous. It also shows how to
-use segmentation information returned from a segmentation model. For more information,
-see [Detecting anomalies in an image](https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/inference-detect-anomalies.html).
-To run the example, supply an image file name and a configuration JSON file with the following format.
-
- {
- "project" : "The Lookout for Vision project name.",
- "model_version" : "The model version.",
- "confidence_limit" : The minimum acceptable confidence. (Float 0 - 1).,
- "coverage_limit" : The maximum acceptable percentage coverage of an anomaly (Float 0 - 1).,
- "anomaly_types_limit" : The maximum number of allowable anomaly types. (Integer),
- "anomaly_label" : "The anomaly label for the type of anomaly that you want to check."
- }
-
-We provide a template JSON configuration file in config.json.
-
-###### models.py
-
-A class that shows how to train and manage a Lookout for Vision model. Used by
-`train_host.py`.
-
-###### projects.py
-
-A class that shows how to create and manage a Lookout for Vision project. Used by
-`train_host.py`.
-
-###### train_host.py
-
-Shows how to create and host a model. The code creates a project, creates a manifest
-file, creates a dataset using the manifest file, and trains a model. Finally, if
-desired, the example shows how to host the model. Used by `train_host.py`.
-
-###### find_running_models.py
-You are charged for the amount of time that an Amazon Lookout for Vision model is
-running (hosted). Use this script to find the running models in the commercial AWS
-partition. You can stop a model by calling the [StopModel](https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/run-stop-model.html) operation.
-
-###### update_dataset.py
-Shows how to add or update images in an Amazon Lookout for Vision dataset.
-
-###### export_datasets.py
-
-Shows how to export the datasets from an Amazon Lookout for Vision project to an
-Amazon S3 location.
-Run this example at a command prompt with the following command.
-
-```
-python export_datasets.py
-```
-
-- `project` - The project that you want to export the datasets from.
-- `destination` - The Amazon S3 path that you want to copy the datasets to.
-
-
-
-#### Hello Lookout for Vision
-
-This example shows you how to get started using Lookout for Vision.
-
-```
-python hello.py
-```
-
-
-#### Create a manifest file
-
-This example shows you how to create a Lookout for Vision manifest file and upload it to Amazon S3.
-
-
-
-
-
-Start the example by running the following at a command prompt:
-
-```
-python datasets.py
-```
-
-
-
-
-
-#### Create, train, and start a model
-
-This example shows you how to create, train, and start a Lookout for Vision model.
-
-
-
-
-
-Start the example by running the following at a command prompt:
-
-
-
-
-
-- `project` - A name for your project.
-- `bucket` - The name of the Amazon S3 bucket in which to store your manifest files and
- training output. The bucket must be in your AWS account and in the same AWS Region as
- the Amazon S3 path supplied for `train` and `test`. For example, `amzn-s3-demo-bucket`.
-- `train` - The Amazon S3 path where your training images are stored. For example,
- `s3://amzn-s3-demo-bucket/circuitboard/train/`.
-- `test` - (Optional) the Amazon S3 path where your test images are stored. For example,
- `s3://amzn-s3-demo-bucket/circuitboard/test/`. If you don't supply a value,
- Lookout for Vision splits the training dataset to create a test dataset.
-
-After training completes, use the performance metrics to decide if the model's
-performance is acceptable. For more information, see
-[Improving your model](https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/improve.html).
-If you are satisfied with the model's performance, the code allows you to start the
-model. After the model starts, use `inference.py` to analyze an image.
-
-**You are charged for the amount of time that your model is running and for the time
-taken to successfully train your model.**
-
-
-
-#### Export the datasets from a project
-
-This example shows you how to export the datasets from a Lookout for Vision project.
-
-
-
-
-
-Start the example by running the following at a command prompt:
-
-```
-python export_datasets.py
-```
-
-
-
-
-
-#### Find a project with a specific tag
-
-This example shows you how to find a Lookout for Vision project with a specific tag.
-
-
-
-
-
-Start the example by running the following at a command prompt:
-
-```
-python find_tag.py
-```
-
-
-
-- tag - The key of the tag that you want to find.
-- value - The value of the tag that you want to find.
-
-For more information about tags, see [Tagging models](https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/tagging-model.html).
-
-
-
-#### List models that are currently hosted
-
-This example shows you how to list Lookout for Vision models that are currently hosted.
-
-
-
-
-
-Start the example by running the following at a command prompt:
-
-```
-python hosting.py
-```
-
-
-
-
-
-### Tests
-
-⚠ Running tests might result in charges to your AWS account.
-
-
-To find instructions for running these tests, see the [README](../../README.md#Tests)
-in the `python` folder.
-
-
-
-
-
-
-## Additional resources
-
-- [Lookout for Vision Developer Guide](https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/what-is.html)
-- [Lookout for Vision API Reference](https://docs.aws.amazon.com/lookout-for-vision/latest/APIReference/Welcome.html)
-- [SDK for Python Lookout for Vision reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lookoutvision.html)
-
-
-
-
----
-
-Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-
-SPDX-License-Identifier: Apache-2.0
\ No newline at end of file
diff --git a/python/example_code/lookoutvision/config.json b/python/example_code/lookoutvision/config.json
deleted file mode 100644
index 63f62153e74..00000000000
--- a/python/example_code/lookoutvision/config.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "project":"project name",
- "model_version" : "model version",
- "confidence_limit" : 0.5,
- "coverage_limit" : 0.1,
- "anomaly_types_limit" :0,
- "anomaly_label" :"label-name"
-}
\ No newline at end of file
diff --git a/python/example_code/lookoutvision/csv_to_manifest.py b/python/example_code/lookoutvision/csv_to_manifest.py
deleted file mode 100644
index 455a3369128..00000000000
--- a/python/example_code/lookoutvision/csv_to_manifest.py
+++ /dev/null
@@ -1,206 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-"""
-Purpose
-Shows how to create an Amazon Lookout for Vision manifest file from a CSV file.
-The CSV file format is image location,anomaly classification (normal or anomaly)
-For example:
-s3://s3bucket/circuitboard/train/anomaly/train_11.jpg,anomaly
-s3://s3bucket/circuitboard/train/normal/train_1.jpg,normal
-
-If necessary, use the bucket argument to specify the Amazon S3 bucket folder for the images.
-More information: https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/ex-csv-manifest.html
-"""
-
-# snippet-start:[python.example_code.lookoutvision.Scenario_CSVtoManifest]
-
-from datetime import datetime, timezone
-import argparse
-import logging
-import csv
-import os
-import json
-
-logger = logging.getLogger(__name__)
-
-
-def check_errors(csv_file):
- """
- Checks for duplicate images and incorrect classifications in a CSV file.
- If duplicate images or invalid anomaly assignments are found, an errors CSV file
- and deduplicated CSV file are created. Only the first
- occurrence of a duplicate is recorded. Other duplicates are recorded in the errors file.
- :param csv_file: The source CSV file
- :return: True if errors or duplicates are found, otherwise false.
- """
-
- logger.info("Checking %s.", csv_file)
-
- errors_found = False
- errors_file = f"{os.path.splitext(csv_file)[0]}_errors.csv"
- deduplicated_file = f"{os.path.splitext(csv_file)[0]}_deduplicated.csv"
-
- with open(csv_file, "r", encoding="UTF-8") as input_file, open(
- deduplicated_file, "w", encoding="UTF-8"
- ) as dedup, open(errors_file, "w", encoding="UTF-8") as errors:
- reader = csv.reader(input_file, delimiter=",")
- dedup_writer = csv.writer(dedup)
- error_writer = csv.writer(errors)
- line = 1
- entries = set()
- for row in reader:
- # Skip empty lines.
- if not "".join(row).strip():
- continue
-
- # Record any incorrect classifications.
- if not row[1].lower() == "normal" and not row[1].lower() == "anomaly":
- error_writer.writerow([line, row[0], row[1], "INVALID_CLASSIFICATION"])
- errors_found = True
-
- # Write first image entry to dedup file and record duplicates.
- key = row[0]
- if key not in entries:
- dedup_writer.writerow(row)
- entries.add(key)
- else:
- error_writer.writerow([line, row[0], row[1], "DUPLICATE"])
- errors_found = True
- line += 1
-
- if errors_found:
- logger.info("Errors found check %s.", errors_file)
- else:
- os.remove(errors_file)
- os.remove(deduplicated_file)
-
- return errors_found
-
-
-def create_manifest_file(csv_file, manifest_file, s3_path):
- """
- Read a CSV file and create an Amazon Lookout for Vision classification manifest file.
- :param csv_file: The source CSV file.
- :param manifest_file: The name of the manifest file to create.
- :param s3_path: The Amazon S3 path to the folder that contains the images.
- """
- logger.info("Processing CSV file %s.", csv_file)
-
- image_count = 0
- anomalous_count = 0
-
- with open(csv_file, newline="", encoding="UTF-8") as csvfile, open(
- manifest_file, "w", encoding="UTF-8"
- ) as output_file:
- image_classifications = csv.reader(csvfile, delimiter=",", quotechar="|")
-
- # Process each row (image) in the CSV file.
- for row in image_classifications:
- # Skip empty lines.
- if not "".join(row).strip():
- continue
-
- source_ref = str(s3_path) + row[0]
- classification = 0
-
- if row[1].lower() == "anomaly":
- classification = 1
- anomalous_count += 1
-
- # Create the JSON line.
- json_line = {}
- json_line["source-ref"] = source_ref
- json_line["anomaly-label"] = str(classification)
-
- metadata = {}
- metadata["confidence"] = 1
- metadata["job-name"] = "labeling-job/anomaly-classification"
- metadata["class-name"] = row[1]
- metadata["human-annotated"] = "yes"
- metadata["creation-date"] = datetime.now(timezone.utc).strftime(
- "%Y-%m-%dT%H:%M:%S.%f"
- )
- metadata["type"] = "groundtruth/image-classification"
-
- json_line["anomaly-label-metadata"] = metadata
-
- output_file.write(json.dumps(json_line))
- output_file.write("\n")
- image_count += 1
-
- logger.info(
- "Finished creating manifest file %s.\n" "Images: %s\nAnomalous: %s",
- manifest_file,
- image_count,
- anomalous_count,
- )
- return image_count, anomalous_count
-
-
-def add_arguments(parser):
- """
- Add command line arguments to the parser.
- :param parser: The command line parser.
- """
-
- parser.add_argument("csv_file", help="The CSV file that you want to process.")
-
- parser.add_argument(
- "--s3_path",
- help="The Amazon S3 bucket and folder path for the images."
- " If not supplied, column 1 is assumed to include the Amazon S3 path.",
- required=False,
- )
-
-
-def main():
- logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
-
- try:
- # Get command line arguments.
- parser = argparse.ArgumentParser(usage=argparse.SUPPRESS)
- add_arguments(parser)
- args = parser.parse_args()
- s3_path = args.s3_path
- if s3_path is None:
- s3_path = ""
-
- csv_file = args.csv_file
- csv_file_no_extension = os.path.splitext(csv_file)[0]
- manifest_file = csv_file_no_extension + ".manifest"
-
- # Create manifest file if there are no duplicate images.
- if check_errors(csv_file):
- print(
- f"Issues found. Use {csv_file_no_extension}_errors.csv "
- "to view duplicates and errors."
- )
- print(
- f"{csv_file}_deduplicated.csv contains the first"
- "occurrence of a duplicate.\n"
- "Update as necessary with the correct information."
- )
- print(f"Re-run the script with {csv_file_no_extension}_deduplicated.csv")
- else:
- print("No duplicates found. Creating manifest file.")
-
- image_count, anomalous_count = create_manifest_file(
- csv_file, manifest_file, s3_path
- )
-
- print(f"Finished creating manifest file: {manifest_file} \n")
-
- normal_count = image_count - anomalous_count
- print(f"Images processed: {image_count}")
- print(f"Normal: {normal_count}")
- print(f"Anomalous: {anomalous_count}")
-
- except FileNotFoundError as err:
- logger.exception("File not found.:%s", err)
- print(f"File not found: {err}. Check your input CSV file.")
-
-
-if __name__ == "__main__":
- main()
-
-# snippet-end:[python.example_code.lookoutvision.Scenario_CSVtoManifest]
diff --git a/python/example_code/lookoutvision/datasets.py b/python/example_code/lookoutvision/datasets.py
deleted file mode 100644
index 689e8483d50..00000000000
--- a/python/example_code/lookoutvision/datasets.py
+++ /dev/null
@@ -1,350 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Purpose
-
-Amazon Lookout for Vision dataset code examples used in the service documentation:
-https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/model-create-dataset.html
-Shows how to create and manage datasets. Also, how to create a manifest file and
-upload to an Amazon S3 bucket.
-"""
-
-import logging
-import time
-from datetime import datetime
-import os
-import json
-
-from botocore.exceptions import ClientError
-
-logger = logging.getLogger(__name__)
-
-
-# snippet-start:[python.example_code.lookoutvision.Datasets]
-class Datasets:
- # snippet-end:[python.example_code.lookoutvision.Datasets]
- """
- Provides example functions for creating, listing, and deleting Lookout for Vision
- datasets. Also shows how to create a manifest file in an Amazon S3 bucket.
- """
-
- # snippet-start:[python.example_code.lookoutvision.CreateDataset]
- @staticmethod
- def create_dataset(lookoutvision_client, project_name, manifest_file, dataset_type):
- """
- Creates a new Lookout for Vision dataset
-
- :param lookoutvision_client: A Lookout for Vision Boto3 client.
- :param project_name: The name of the project in which you want to
- create a dataset.
- :param bucket: The bucket that contains the manifest file.
- :param manifest_file: The path and name of the manifest file.
- :param dataset_type: The type of the dataset (train or test).
- """
- try:
- bucket, key = manifest_file.replace("s3://", "").split("/", 1)
- logger.info("Creating %s dataset type...", dataset_type)
- dataset = {
- "GroundTruthManifest": {"S3Object": {"Bucket": bucket, "Key": key}}
- }
- response = lookoutvision_client.create_dataset(
- ProjectName=project_name,
- DatasetType=dataset_type,
- DatasetSource=dataset,
- )
- logger.info("Dataset Status: %s", response["DatasetMetadata"]["Status"])
- logger.info(
- "Dataset Status Message: %s",
- response["DatasetMetadata"]["StatusMessage"],
- )
- logger.info("Dataset Type: %s", response["DatasetMetadata"]["DatasetType"])
-
- # Wait until either created or failed.
- finished = False
- status = ""
- dataset_description = {}
- while finished is False:
- dataset_description = lookoutvision_client.describe_dataset(
- ProjectName=project_name, DatasetType=dataset_type
- )
- status = dataset_description["DatasetDescription"]["Status"]
-
- if status == "CREATE_IN_PROGRESS":
- logger.info("Dataset creation in progress...")
- time.sleep(2)
- elif status == "CREATE_COMPLETE":
- logger.info("Dataset created.")
- finished = True
- else:
- logger.info(
- "Dataset creation failed: %s",
- dataset_description["DatasetDescription"]["StatusMessage"],
- )
- finished = True
-
- if status != "CREATE_COMPLETE":
- message = dataset_description["DatasetDescription"]["StatusMessage"]
- logger.exception("Couldn't create dataset: %s", message)
- raise Exception(f"Couldn't create dataset: {message}")
-
- except ClientError:
- logger.exception("Service error: Couldn't create dataset.")
- raise
-
- # snippet-end:[python.example_code.lookoutvision.CreateDataset]
-
- # snippet-start:[python.example_code.lookoutvision.Scenario_CreateManifestFile]
- @staticmethod
- def create_manifest_file_s3(s3_resource, image_s3_path, manifest_s3_path):
- """
- Creates a manifest file and uploads to Amazon S3.
-
- :param s3_resource: A Boto3 Amazon S3 resource.
- :param image_s3_path: The Amazon S3 path to the images referenced by the
- manifest file. The images must be in an Amazon S3 bucket
- with the following folder structure.
- s3://amzn-s3-demo-bucket//
- normal/
- anomaly/
- Place normal images in the normal folder and anomalous
- images in the anomaly folder.
- :param manifest_s3_path: The Amazon S3 location in which to store the created
- manifest file.
- """
- output_manifest_file = "temp.manifest"
- try:
- # Current date and time in manifest file format.
- dttm = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")
-
- # Get bucket and folder from image and manifest file paths.
- bucket, prefix = image_s3_path.replace("s3://", "").split("/", 1)
- if prefix[-1] != "/":
- prefix += "/"
- manifest_bucket, manifest_prefix = manifest_s3_path.replace(
- "s3://", ""
- ).split("/", 1)
-
- with open(output_manifest_file, "w") as mfile:
- logger.info("Creating manifest file")
- src_bucket = s3_resource.Bucket(bucket)
-
- # Create JSON lines for anomalous images.
- for obj in src_bucket.objects.filter(
- Prefix=prefix + "anomaly/", Delimiter="/"
- ):
- image_path = f"s3://{src_bucket.name}/{obj.key}"
- manifest = Datasets.create_json_line(image_path, "anomaly", dttm)
- mfile.write(json.dumps(manifest) + "\n")
-
- # Create json lines for normal images.
- for obj in src_bucket.objects.filter(
- Prefix=prefix + "normal/", Delimiter="/"
- ):
- image_path = f"s3://{src_bucket.name}/{obj.key}"
- manifest = Datasets.create_json_line(image_path, "normal", dttm)
- mfile.write(json.dumps(manifest) + "\n")
-
- logger.info("Uploading manifest file to %s", manifest_s3_path)
- s3_resource.Bucket(manifest_bucket).upload_file(
- output_manifest_file, manifest_prefix
- )
- except ClientError:
- logger.exception("Error uploading manifest.")
- raise
- except Exception:
- logger.exception("Error uploading manifest.")
- raise
- else:
- logger.info("Completed manifest file creation and upload.")
- finally:
- try:
- os.remove(output_manifest_file)
- except FileNotFoundError:
- pass
-
- @staticmethod
- def create_json_line(image, class_name, dttm):
- """
- Creates a single JSON line for an image.
-
- :param image: The S3 location for the image.
- :param class_name: The class of the image (normal or anomaly)
- :param dttm: The date and time that the JSON is created.
- """
-
- label = 0
- if class_name == "normal":
- label = 0
- elif class_name == "anomaly":
- label = 1
- else:
- logger.error("Unexpected label value: %s for %s", label, image)
- raise Exception(f"Unexpected label value: {label} for {image}")
-
- manifest = {
- "source-ref": image,
- "anomaly-label": label,
- "anomaly-label-metadata": {
- "confidence": 1,
- "job-name": "labeling-job/anomaly-label",
- "class-name": class_name,
- "human-annotated": "yes",
- "creation-date": dttm,
- "type": "groundtruth/image-classification",
- },
- }
- return manifest
-
- # snippet-end:[python.example_code.lookoutvision.Scenario_CreateManifestFile]
-
- # snippet-start:[python.example_code.lookoutvision.DeleteDataset]
- @staticmethod
- def delete_dataset(lookoutvision_client, project_name, dataset_type):
- """
- Deletes a Lookout for Vision dataset
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param project_name: The name of the project that contains the dataset that
- you want to delete.
- :param dataset_type: The type (train or test) of the dataset that you
- want to delete.
- """
- try:
- logger.info(
- "Deleting the %s dataset for project %s.", dataset_type, project_name
- )
- lookoutvision_client.delete_dataset(
- ProjectName=project_name, DatasetType=dataset_type
- )
- logger.info("Dataset deleted.")
- except ClientError:
- logger.exception("Service error: Couldn't delete dataset.")
- raise
-
- # snippet-end:[python.example_code.lookoutvision.DeleteDataset]
-
- # snippet-start:[python.example_code.lookoutvision.DescribeDataset]
- @staticmethod
- def describe_dataset(lookoutvision_client, project_name, dataset_type):
- """
- Gets information about a Lookout for Vision dataset.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param project_name: The name of the project that contains the dataset that
- you want to describe.
- :param dataset_type: The type (train or test) of the dataset that you want
- to describe.
- """
- try:
- response = lookoutvision_client.describe_dataset(
- ProjectName=project_name, DatasetType=dataset_type
- )
- print(f"Name: {response['DatasetDescription']['ProjectName']}")
- print(f"Type: {response['DatasetDescription']['DatasetType']}")
- print(f"Status: {response['DatasetDescription']['Status']}")
- print(f"Message: {response['DatasetDescription']['StatusMessage']}")
- print(f"Images: {response['DatasetDescription']['ImageStats']['Total']}")
- print(f"Labeled: {response['DatasetDescription']['ImageStats']['Labeled']}")
- print(f"Normal: {response['DatasetDescription']['ImageStats']['Normal']}")
- print(f"Anomaly: {response['DatasetDescription']['ImageStats']['Anomaly']}")
- except ClientError:
- logger.exception("Service error: problem listing datasets.")
- raise
- print("Done.")
-
- # snippet-end:[python.example_code.lookoutvision.DescribeDataset]
-
- # snippet-start:[python.example_code.lookoutvision.UpdateDatasetEntries]
- @staticmethod
- def update_dataset_entries(
- lookoutvision_client, project_name, dataset_type, updates_file
- ):
- """
- Adds dataset entries to an Amazon Lookout for Vision dataset.
- :param lookoutvision_client: The Amazon Rekognition Custom Labels Boto3 client.
- :param project_name: The project that contains the dataset that you want to update.
- :param dataset_type: The type of the dataset that you want to update (train or test).
- :param updates_file: The manifest file of JSON lines that contains the updates.
- """
-
- try:
- status = ""
- status_message = ""
- manifest_file = ""
-
- # Update dataset entries.
- logger.info(
- f"Updating {dataset_type} dataset for project {project_name}"
- f"with entries from {updates_file}."
- )
-
- with open(updates_file) as f:
- manifest_file = f.read()
-
- lookoutvision_client.update_dataset_entries(
- ProjectName=project_name,
- DatasetType=dataset_type,
- Changes=manifest_file,
- )
-
- finished = False
-
- while not finished:
- dataset = lookoutvision_client.describe_dataset(
- ProjectName=project_name, DatasetType=dataset_type
- )
-
- status = dataset["DatasetDescription"]["Status"]
- status_message = dataset["DatasetDescription"]["StatusMessage"]
-
- if status == "UPDATE_IN_PROGRESS":
- logger.info(
- (f"Updating {dataset_type} dataset for project {project_name}.")
- )
- time.sleep(5)
- continue
-
- if status == "UPDATE_FAILED_ROLLBACK_IN_PROGRESS":
- logger.info(
- (
- f"Update failed, rolling back {dataset_type} dataset for project {project_name}."
- )
- )
- time.sleep(5)
- continue
-
- if status == "UPDATE_COMPLETE":
- logger.info(
- f"Dataset updated: {status} : {status_message} : {dataset_type} dataset for project {project_name}."
- )
- finished = True
- continue
-
- if status == "UPDATE_FAILED_ROLLBACK_COMPLETE":
- logger.info(
- f"Rollback completed after update failure: {status} : {status_message} : {dataset_type} dataset for project {project_name}."
- )
- finished = True
- continue
-
- logger.exception(
- f"Failed. Unexpected state for dataset update: {status} : {status_message} : "
- "{dataset_type} dataset for project {project_name}."
- )
- raise Exception(
- f"Failed. Unexpected state for dataset update: {status} : "
- "{status_message} :{dataset_type} dataset for project {project_name}."
- )
-
- logger.info(f"Added entries to dataset.")
-
- return status, status_message
-
- except ClientError as err:
- logger.exception(
- f"Couldn't update dataset: {err.response['Error']['Message']}"
- )
- raise
-
- # snippet-end:[python.example_code.lookoutvision.UpdateDatasetEntries]
diff --git a/python/example_code/lookoutvision/export_datasets.py b/python/example_code/lookoutvision/export_datasets.py
deleted file mode 100644
index b58eb9198e8..00000000000
--- a/python/example_code/lookoutvision/export_datasets.py
+++ /dev/null
@@ -1,269 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-# snippet-start:[python.example_code.lookoutvision.Scenario_ExportDatasets]
-
-"""
-Purpose
-
-Shows how to export the datasets (manifest files and images)
-from an Amazon Lookout for Vision project to a new Amazon
-S3 location.
-"""
-
-import argparse
-import json
-import logging
-
-import boto3
-from botocore.exceptions import ClientError
-
-logger = logging.getLogger(__name__)
-
-
-def copy_file(s3_resource, source_file, destination_file):
- """
- Copies a file from a source Amazon S3 folder to a destination
- Amazon S3 folder.
- The destination can be in a different S3 bucket.
- :param s3: An Amazon S3 Boto3 resource.
- :param source_file: The Amazon S3 path to the source file.
- :param destination_file: The destination Amazon S3 path for
- the copy operation.
- """
-
- source_bucket, source_key = source_file.replace("s3://", "").split("/", 1)
- destination_bucket, destination_key = destination_file.replace("s3://", "").split(
- "/", 1
- )
-
- try:
- bucket = s3_resource.Bucket(destination_bucket)
- dest_object = bucket.Object(destination_key)
- dest_object.copy_from(CopySource={"Bucket": source_bucket, "Key": source_key})
- dest_object.wait_until_exists()
- logger.info("Copied %s to %s", source_file, destination_file)
- except ClientError as error:
- if error.response["Error"]["Code"] == "404":
- error_message = (
- f"Failed to copy {source_file} to "
- f"{destination_file}. : {error.response['Error']['Message']}"
- )
- logger.warning(error_message)
- error.response["Error"]["Message"] = error_message
- raise
-
-
-def upload_manifest_file(s3_resource, manifest_file, destination):
- """
- Uploads a manifest file to a destination Amazon S3 folder.
- :param s3: An Amazon S3 Boto3 resource.
- :param manifest_file: The manifest file that you want to upload.
- :destination: The Amazon S3 folder location to upload the manifest
- file to.
- """
-
- destination_bucket, destination_key = destination.replace("s3://", "").split("/", 1)
-
- bucket = s3_resource.Bucket(destination_bucket)
-
- put_data = open(manifest_file, "rb")
- obj = bucket.Object(destination_key + manifest_file)
-
- try:
- obj.put(Body=put_data)
- obj.wait_until_exists()
- logger.info("Put manifest file '%s' to bucket '%s'.", obj.key, obj.bucket_name)
- except ClientError:
- logger.exception(
- "Couldn't put manifest file '%s' to bucket '%s'.", obj.key, obj.bucket_name
- )
- raise
- finally:
- if getattr(put_data, "close", None):
- put_data.close()
-
-
-def get_dataset_types(lookoutvision_client, project):
- """
- Determines the types of the datasets (train or test) in an
- Amazon Lookout for Vision project.
- :param lookoutvision_client: A Lookout for Vision Boto3 client.
- :param project: The Lookout for Vision project that you want to check.
- :return: The dataset types in the project.
- """
-
- try:
- response = lookoutvision_client.describe_project(ProjectName=project)
-
- datasets = []
-
- for dataset in response["ProjectDescription"]["Datasets"]:
- if dataset["Status"] in ("CREATE_COMPLETE", "UPDATE_COMPLETE"):
- datasets.append(dataset["DatasetType"])
- return datasets
-
- except lookoutvision_client.exceptions.ResourceNotFoundException:
- logger.exception("Project %s not found.", project)
- raise
-
-
-def process_json_line(s3_resource, entry, dataset_type, destination):
- """
- Creates a JSON line for a new manifest file, copies image and mask to
- destination.
- :param s3_resource: An Amazon S3 Boto3 resource.
- :param entry: A JSON line from the manifest file.
- :param dataset_type: The type (train or test) of the dataset that
- you want to create the manifest file for.
- :param destination: The destination Amazon S3 folder for the manifest
- file and dataset images.
- :return: A JSON line with details for the destination location.
- """
- entry_json = json.loads(entry)
-
- print(f"source: {entry_json['source-ref']}")
-
- # Use existing folder paths to ensure console added image names don't clash.
- bucket, key = entry_json["source-ref"].replace("s3://", "").split("/", 1)
- logger.info("Source location: %s/%s", bucket, key)
-
- destination_image_location = destination + dataset_type + "/images/" + key
-
- copy_file(s3_resource, entry_json["source-ref"], destination_image_location)
-
- # Update JSON for writing.
- entry_json["source-ref"] = destination_image_location
-
- if "anomaly-mask-ref" in entry_json:
- source_anomaly_ref = entry_json["anomaly-mask-ref"]
- mask_bucket, mask_key = source_anomaly_ref.replace("s3://", "").split("/", 1)
-
- destination_mask_location = destination + dataset_type + "/masks/" + mask_key
- entry_json["anomaly-mask-ref"] = destination_mask_location
-
- copy_file(s3_resource, source_anomaly_ref, entry_json["anomaly-mask-ref"])
-
- return entry_json
-
-
-def write_manifest_file(
- lookoutvision_client, s3_resource, project, dataset_type, destination
-):
- """
- Creates a manifest file for a dataset. Copies the manifest file and
- dataset images (and masks, if present) to the specified Amazon S3 destination.
- :param lookoutvision_client: A Lookout for Vision Boto3 client.
- :param project: The Lookout for Vision project that you want to use.
- :param dataset_type: The type (train or test) of the dataset that
- you want to create the manifest file for.
- :param destination: The destination Amazon S3 folder for the manifest file
- and dataset images.
- """
-
- try:
- # Create a reusable Paginator
- paginator = lookoutvision_client.get_paginator("list_dataset_entries")
-
- # Create a PageIterator from the Paginator
- page_iterator = paginator.paginate(
- ProjectName=project,
- DatasetType=dataset_type,
- PaginationConfig={"PageSize": 100},
- )
-
- output_manifest_file = dataset_type + ".manifest"
-
- # Create manifest file then upload to Amazon S3 with images.
- with open(output_manifest_file, "w", encoding="utf-8") as manifest_file:
- for page in page_iterator:
- for entry in page["DatasetEntries"]:
- try:
- entry_json = process_json_line(
- s3_resource, entry, dataset_type, destination
- )
-
- manifest_file.write(json.dumps(entry_json) + "\n")
-
- except ClientError as error:
- if error.response["Error"]["Code"] == "404":
- print(error.response["Error"]["Message"])
- print(f"Excluded JSON line: {entry}")
- else:
- raise
- upload_manifest_file(
- s3_resource, output_manifest_file, destination + "datasets/"
- )
-
- except ClientError:
- logger.exception("Problem getting dataset_entries")
- raise
-
-
-def export_datasets(lookoutvision_client, s3_resource, project, destination):
- """
- Exports the datasets from an Amazon Lookout for Vision project to a specified
- Amazon S3 destination.
- :param project: The Lookout for Vision project that you want to use.
- :param destination: The destination Amazon S3 folder for the exported datasets.
- """
- # Add trailing backslash, if missing.
- destination = destination if destination[-1] == "/" else destination + "/"
-
- print(f"Exporting project {project} datasets to {destination}.")
-
- # Get each dataset and export to destination.
-
- dataset_types = get_dataset_types(lookoutvision_client, project)
- for dataset in dataset_types:
- logger.info("Copying %s dataset to %s.", dataset, destination)
-
- write_manifest_file(
- lookoutvision_client, s3_resource, project, dataset, destination
- )
-
- print("Exported dataset locations")
- for dataset in dataset_types:
- print(f" {dataset}: {destination}datasets/{dataset}.manifest")
-
- print("Done.")
-
-
-def add_arguments(parser):
- """
- Adds command line arguments to the parser.
- :param parser: The command line parser.
- """
-
- parser.add_argument("project", help="The project that contains the dataset.")
- parser.add_argument("destination", help="The destination Amazon S3 folder.")
-
-
-def main():
- """
- Exports the datasets from an Amazon Lookout for Vision project to a
- destination Amazon S3 location.
- """
- logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
- parser = argparse.ArgumentParser(usage=argparse.SUPPRESS)
- add_arguments(parser)
-
- args = parser.parse_args()
-
- try:
- session = boto3.Session(profile_name="lookoutvision-access")
- lookoutvision_client = session.client("lookoutvision")
- s3_resource = session.resource("s3")
-
- export_datasets(
- lookoutvision_client, s3_resource, args.project, args.destination
- )
- except ClientError as err:
- logger.exception(err)
- print(f"Failed: {format(err)}")
-
-
-if __name__ == "__main__":
- main()
-
-# snippet-end:[python.example_code.lookoutvision.Scenario_ExportDatasets]
diff --git a/python/example_code/lookoutvision/find_running_models.py b/python/example_code/lookoutvision/find_running_models.py
deleted file mode 100644
index df3d443e8cf..00000000000
--- a/python/example_code/lookoutvision/find_running_models.py
+++ /dev/null
@@ -1,158 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-"""
-Purpose: Displays a list of running Amazon Lookout for Vision
-models across all accessible AWS Regions in the commercial
-AWS partition. For accurate results, install the latest Boto3
-client.
-"""
-
-# snippet-start:[python.example_code.lookoutvision.Scenario_FindRunningModels]
-
-import logging
-import boto3
-
-from boto3.session import Session
-
-
-from botocore.exceptions import ClientError, EndpointConnectionError
-
-
-logger = logging.getLogger(__name__)
-
-
-def find_running_models_in_project(lfv_client, project_name):
- """
- Gets a list of running models in a project.
- :param lookoutvision_client: A Boto3 Amazon Lookout for Vision client.
- param project_name: The name of the project that you want to use.
- return: A list of running models. Empty if no models are
- running in the project.
- """
-
- logger.info("Finding running models in project: %s", project_name)
- running_models = []
-
- # Get a list of models in the current project.
-
- paginator = lfv_client.get_paginator("list_models")
- page_iterator = paginator.paginate(ProjectName=project_name)
-
- for page in page_iterator:
- for model in page["Models"]:
- # Get model description and store hosted state, if model is running.
-
- model_description = lfv_client.describe_model(
- ProjectName=project_name, ModelVersion=model["ModelVersion"]
- )
-
- logger.info(
- "Checking: %s", model_description["ModelDescription"]["ModelArn"]
- )
-
- if model_description["ModelDescription"]["Status"] == "HOSTED":
- running_model = {
- "Project": project_name,
- "ARN": model_description["ModelDescription"]["ModelArn"],
- "Version": model_description["ModelDescription"]["ModelVersion"],
- }
- running_models.append(running_model)
- logger.info(
- "Running model ARN: %s Version %s",
- model_description["ModelDescription"]["ModelArn"],
- model_description["ModelDescription"]["ModelVersion"],
- )
-
- logger.info("Done finding running models in project: %s", project_name)
-
- return running_models
-
-
-def display_running_models(running_model_regions):
- """
- Displays running model information.
- :param running_model_region: A list of AWS Regions
- and models that are running within each AWS Region.
- """
- count = 0
-
- if running_model_regions:
- print("Running models.\n")
- for region in running_model_regions:
- print(region["Region"])
- for model in region["Models"]:
- print(f" Project: {model['Project']}")
- print(f" Version: {model['Version']}")
- print(f" ARN: {model['ARN']}\n")
- count += 1
-
- print(f"There is {count} running model(s).")
-
-
-def find_running_models(boto3_session):
- """
- Finds the running Lookout for Vision models across all accessible
- AWS Regions.
-
- :param boto3_session A Boto3 session initialized with a credentials profile.
- :return: A list of running models.
- """
-
- running_models = []
-
- # Get a list of Lookout for Vision accessible AWS Regions in
- # the AWS commercial partition.
- # Make sure your Boto3 client is up to date as it stores this list.
- regions = boto3_session.get_available_regions(service_name="lookoutvision")
-
- # Loop through each AWS Region and collect running models.
- for region in regions:
- logger.info("Checking %s", region)
- region_info = {}
- region_info["Region"] = region
- region_info["Models"] = []
- running_models_in_region = []
-
- lfv_client = boto3_session.client("lookoutvision", region_name=region)
-
- # Get the projects in the current AWS Region.
-
- paginator = lfv_client.get_paginator("list_projects")
- page_iterator = paginator.paginate()
-
- for page in page_iterator:
- for project in page["Projects"]:
- running_models_in_project = find_running_models_in_project(
- lfv_client, project["ProjectName"]
- )
- for running_model in running_models_in_project:
- running_models_in_region.append(running_model)
-
- region_info["Models"] = running_models_in_region
-
- if region_info["Models"]:
- running_models.append(region_info)
-
- return running_models
-
-
-def main():
- logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
-
- try:
- session = boto3.Session(profile_name="lookoutvision-access")
- running_models = find_running_models(session)
- display_running_models(running_models)
-
- except TypeError as err:
- print("Couldn't get available AWS Regions: " + format(err))
- except ClientError as err:
- print("Service error occurred: " + format(err))
- except EndpointConnectionError as err:
- logger.info("Problem calling endpoint: %s", format(err))
- raise
-
-
-if __name__ == "__main__":
- main()
-# snippet-end:[python.example_code.lookoutvision.Scenario_FindRunningModels]
diff --git a/python/example_code/lookoutvision/find_tag.py b/python/example_code/lookoutvision/find_tag.py
deleted file mode 100644
index 9967ffde23a..00000000000
--- a/python/example_code/lookoutvision/find_tag.py
+++ /dev/null
@@ -1,126 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Purpose
-
-Shows how to find a tag value that's associated with models within Amazon Lookout for
-Vision projects.
-"""
-
-# snippet-start:[python.example_code.lookoutvision.Scenario_FindTagInProjects]
-import logging
-import argparse
-import boto3
-
-from botocore.exceptions import ClientError
-
-
-logger = logging.getLogger(__name__)
-
-
-def find_tag(tags, key, value):
- """
- Finds a tag in the supplied list of tags.
-
- :param tags: A list of tags associated with a Lookout for Vision model.
- :param key: The tag to search for.
- :param value: The tag key value to search for.
- :return: True if the tag value exists, otherwise False.
- """
-
- found = False
- for tag in tags:
- if key == tag["Key"]:
- logger.info("\t\tMatch found for tag: %s value: %s.", key, value)
- found = True
- break
- return found
-
-
-def find_tag_in_projects(lookoutvision_client, key, value):
- """
- Finds Lookout for Vision models tagged with the supplied key and value.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param key: The tag key to find.
- :param value: The value of the tag that you want to find.
- return: A list of matching model versions (and model projects) that were found.
- """
- try:
- found_tags = []
- found = False
- projects = lookoutvision_client.list_projects()
- # Iterate through each project and models within a project.
- for project in projects["Projects"]:
- logger.info("Searching project: %s ...", project["ProjectName"])
-
- response_models = lookoutvision_client.list_models(
- ProjectName=project["ProjectName"]
- )
- for model in response_models["Models"]:
- model_description = lookoutvision_client.describe_model(
- ProjectName=project["ProjectName"],
- ModelVersion=model["ModelVersion"],
- )
- tags = lookoutvision_client.list_tags_for_resource(
- ResourceArn=model_description["ModelDescription"]["ModelArn"]
- )
-
- logger.info(
- "\tSearching model: %s for tag: %s value: %s.",
- model_description["ModelDescription"]["ModelArn"],
- key,
- value,
- )
- if find_tag(tags["Tags"], key, value) is True:
- found = True
- logger.info(
- "\t\tMATCH: Project: %s: model version %s",
- project["ProjectName"],
- model_description["ModelDescription"]["ModelVersion"],
- )
- found_tags.append(
- {
- "Project": project["ProjectName"],
- "ModelVersion": model_description["ModelDescription"][
- "ModelVersion"
- ],
- }
- )
- if found is False:
- logger.info("No match for tag %s with value %s.", key, value)
- except ClientError:
- logger.exception("Problem finding tags.")
- raise
- else:
- return found_tags
-
-
-def main():
- logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
- parser = argparse.ArgumentParser(usage=argparse.SUPPRESS)
- parser.add_argument("tag", help="The tag that you want to find.")
- parser.add_argument("value", help="The tag value that you want to find.")
- args = parser.parse_args()
- key = args.tag
- value = args.value
-
- session = boto3.Session(profile_name="lookoutvision-access")
-
- lookoutvision_client = session.client("lookoutvision")
-
- print(f"Searching your models for tag: {key} with value: {value}.")
- tagged_models = find_tag_in_projects(lookoutvision_client, key, value)
-
- print("Matched models\n--------------")
- if len(tagged_models) > 0:
- for model in tagged_models:
- print(f"Project: {model['Project']}. model version:{model['ModelVersion']}")
- else:
- print("No matches found.")
-
-
-if __name__ == "__main__":
- main()
-# snippet-end:[python.example_code.lookoutvision.Scenario_FindTagInProjects]
diff --git a/python/example_code/lookoutvision/hello.py b/python/example_code/lookoutvision/hello.py
deleted file mode 100644
index 4b47f4fd471..00000000000
--- a/python/example_code/lookoutvision/hello.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-# snippet-start:[python.example_code.lookoutvision.Hello]
-
-"""
-This example shows how to list your Amazon Lookout for Vision projects.
-If you haven't previously created a project in the current AWS Region,
-the response is an empty list, however it confirms that you can call the
-Lookout for Vision API.
-"""
-from botocore.exceptions import ClientError
-import boto3
-
-
-class Hello:
- """Hello class for Amazon Lookout for Vision"""
-
- @staticmethod
- def list_projects(lookoutvision_client):
- """
- Lists information about the projects that are in your AWS account
- and in the current AWS Region.
-
- : param lookoutvision_client: A Boto3 Lookout for Vision client.
- """
- try:
- response = lookoutvision_client.list_projects()
- for project in response["Projects"]:
- print("Project: " + project["ProjectName"])
- print("ARN: " + project["ProjectArn"])
- print()
- print("Done!")
- except ClientError as err:
- print(f"Couldn't list projects. \n{err}")
- raise
-
-
-def main():
- session = boto3.Session(profile_name="lookoutvision-access")
- lookoutvision_client = session.client("lookoutvision")
-
- Hello.list_projects(lookoutvision_client)
-
-
-if __name__ == "__main__":
- main()
-
-# snippet-end:[python.example_code.lookoutvision.Hello]
diff --git a/python/example_code/lookoutvision/hosting.py b/python/example_code/lookoutvision/hosting.py
deleted file mode 100644
index de450e643ca..00000000000
--- a/python/example_code/lookoutvision/hosting.py
+++ /dev/null
@@ -1,173 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Purpose
-
-Amazon Lookout for Vision model hosting examples used in the service documentation:
-https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/running-model.html
-
-Shows how to start and stop a model. Also, how to get a list of running models
-in your AWS account.
-"""
-
-import time
-import logging
-
-from botocore.exceptions import ClientError
-
-logger = logging.getLogger(__name__)
-
-
-# snippet-start:[python.example_code.lookoutvision.Hosting]
-class Hosting:
- # snippet-end:[python.example_code.lookoutvision.Hosting]
- """
- Shows how to start and stop a Lookout for Vision Model. Also shows how to list the
- models that are currently running.
- """
-
- # snippet-start:[python.example_code.lookoutvision.StartModel]
- @staticmethod
- def start_model(
- lookoutvision_client, project_name, model_version, min_inference_units
- ):
- """
- Starts the hosting of a Lookout for Vision model.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param project_name: The name of the project that contains the version of the
- model that you want to start hosting.
- :param model_version: The version of the model that you want to start hosting.
- :param min_inference_units: The number of inference units to use for hosting.
- """
- try:
- logger.info(
- "Starting model version %s for project %s", model_version, project_name
- )
- lookoutvision_client.start_model(
- ProjectName=project_name,
- ModelVersion=model_version,
- MinInferenceUnits=min_inference_units,
- )
- print("Starting hosting...")
-
- status = ""
- finished = False
-
- # Wait until hosted or failed.
- while finished is False:
- model_description = lookoutvision_client.describe_model(
- ProjectName=project_name, ModelVersion=model_version
- )
- status = model_description["ModelDescription"]["Status"]
-
- if status == "STARTING_HOSTING":
- logger.info("Host starting in progress...")
- time.sleep(10)
- continue
-
- if status == "HOSTED":
- logger.info("Model is hosted and ready for use.")
- finished = True
- continue
-
- logger.info("Model hosting failed and the model can't be used.")
- finished = True
-
- if status != "HOSTED":
- logger.error("Error hosting model: %s", status)
- raise Exception(f"Error hosting model: {status}")
- except ClientError:
- logger.exception("Couldn't host model.")
- raise
-
- # snippet-end:[python.example_code.lookoutvision.StartModel]
-
- # snippet-start:[python.example_code.lookoutvision.StopModel]
- @staticmethod
- def stop_model(lookoutvision_client, project_name, model_version):
- """
- Stops a running Lookout for Vision Model.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param project_name: The name of the project that contains the version of
- the model that you want to stop hosting.
- :param model_version: The version of the model that you want to stop hosting.
- """
- try:
- logger.info("Stopping model version %s for %s", model_version, project_name)
- response = lookoutvision_client.stop_model(
- ProjectName=project_name, ModelVersion=model_version
- )
- logger.info("Stopping hosting...")
-
- status = response["Status"]
- finished = False
-
- # Wait until stopped or failed.
- while finished is False:
- model_description = lookoutvision_client.describe_model(
- ProjectName=project_name, ModelVersion=model_version
- )
- status = model_description["ModelDescription"]["Status"]
-
- if status == "STOPPING_HOSTING":
- logger.info("Host stopping in progress...")
- time.sleep(10)
- continue
-
- if status == "TRAINED":
- logger.info("Model is no longer hosted.")
- finished = True
- continue
-
- logger.info("Failed to stop model: %s ", status)
- finished = True
-
- if status != "TRAINED":
- logger.error("Error stopping model: %s", status)
- raise Exception(f"Error stopping model: {status}")
- except ClientError:
- logger.exception("Couldn't stop hosting model.")
- raise
-
- # snippet-end:[python.example_code.lookoutvision.StopModel]
-
- # snippet-start:[python.example_code.lookoutvision.Scenario_ListHostedModels]
- @staticmethod
- def list_hosted(lookoutvision_client):
- """
- Displays a list of models in your account that are currently hosted.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- """
- try:
- response = lookoutvision_client.list_projects()
- hosted = 0
- print("Hosted models\n-------------")
-
- for project in response["Projects"]:
- response_models = lookoutvision_client.list_models(
- ProjectName=project["ProjectName"]
- )
-
- for model in response_models["Models"]:
- model_description = lookoutvision_client.describe_model(
- ProjectName=project["ProjectName"],
- ModelVersion=model["ModelVersion"],
- )
-
- if model_description["ModelDescription"]["Status"] == "HOSTED":
- print(
- f"Project: {project['ProjectName']} Model version: "
- f"{model['ModelVersion']}"
- )
- hosted += 1
- print(f"{hosted} model(s) hosted")
- except ClientError:
- logger.exception("Problem listing hosted models.")
- raise
-
-
-# snippet-end:[python.example_code.lookoutvision.Scenario_ListHostedModels]
diff --git a/python/example_code/lookoutvision/inference.py b/python/example_code/lookoutvision/inference.py
deleted file mode 100644
index 1b8a7a42a2a..00000000000
--- a/python/example_code/lookoutvision/inference.py
+++ /dev/null
@@ -1,308 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Purpose
-
-Uses a trained Amazon Lookout for Vision model to detect anomalies
-in an image. The image can be local or in an S3 bucket.
-"""
-
-import argparse
-import logging
-import os
-import json
-import imghdr
-import boto3
-
-from botocore.exceptions import ClientError
-
-logger = logging.getLogger(__name__)
-
-
-# snippet-start:[python.example_code.lookoutvision.DetectAnomalies]
-class Inference:
- """
- Shows how to detect anomalies in an image using a trained Lookout for Vision model.
- """
-
- @staticmethod
- def detect_anomalies(lookoutvision_client, project_name, model_version, photo):
- """
- Calls DetectAnomalies using the supplied project, model version, and image.
- :param lookoutvision_client: A Lookout for Vision Boto3 client.
- :param project: The project that contains the model that you want to use.
- :param model_version: The version of the model that you want to use.
- :param photo: The photo that you want to analyze.
- :return: The DetectAnomalyResult object that contains the analysis results.
- """
-
- image_type = imghdr.what(photo)
- if image_type == "jpeg":
- content_type = "image/jpeg"
- elif image_type == "png":
- content_type = "image/png"
- else:
- logger.info("Image type not valid for %s", photo)
- raise ValueError(
- f"File format not valid. Supply a jpeg or png format file: {photo}"
- )
-
- # Get images bytes for call to detect_anomalies.
- with open(photo, "rb") as image:
- response = lookoutvision_client.detect_anomalies(
- ProjectName=project_name,
- ContentType=content_type,
- Body=image.read(),
- ModelVersion=model_version,
- )
-
- return response["DetectAnomalyResult"]
-
- @staticmethod
- def download_from_s3(s3_resource, photo):
- """
- Downloads an image from an S3 bucket.
-
- :param s3_resource: A Boto3 Amazon S3 resource.
- :param photo: The Amazon S3 path of a photo to download.
- return: The local path to the downloaded file.
- """
- try:
- bucket, key = photo.replace("s3://", "").split("/", 1)
- local_file = os.path.basename(photo)
- except ValueError:
- logger.exception("Couldn't get S3 info for %s", photo)
- raise
-
- try:
- logger.info("Downloading %s", photo)
- s3_resource.Bucket(bucket).download_file(key, local_file)
- except ClientError:
- logger.exception("Couldn't download %s from S3.", photo)
- raise
-
- return local_file
-
- @staticmethod
- def reject_on_classification(image, prediction, confidence_limit):
- """
- Returns True if the anomaly confidence is greater than or equal to
- the supplied confidence limit.
- :param image: The name of the image file that was analyzed.
- :param prediction: The DetectAnomalyResult object returned from DetectAnomalies.
- :param confidence_limit: The minimum acceptable confidence (float 0 - 1).
- :return: True if the error condition indicates an anomaly, otherwise False.
- """
-
- reject = False
-
- logger.info("Checking classification for %s", image)
-
- if prediction["IsAnomalous"] and prediction["Confidence"] >= confidence_limit:
- reject = True
- reject_info = (
- f"Rejected: Anomaly confidence ({prediction['Confidence']:.2%}) is greater"
- f" than limit ({confidence_limit:.2%})"
- )
- logger.info("%s", reject_info)
-
- if not reject:
- logger.info("No anomalies found.")
- return reject
-
- @staticmethod
- def reject_on_anomaly_types(
- image, prediction, confidence_limit, anomaly_types_limit
- ):
- """
- Checks if the number of anomaly types is greater than the anomaly types
- limit and if the prediction confidence is greater than the confidence limit.
- :param image: The name of the image file that was analyzed.
- :param prediction: The DetectAnomalyResult object returned from DetectAnomalies.
- :param confidence: The minimum acceptable confidence (float 0 - 1).
- :param anomaly_types_limit: The maximum number of allowable anomaly types (int).
- :return: True if the error condition indicates an anomaly, otherwise False.
- """
-
- logger.info("Checking number of anomaly types for %s", image)
-
- reject = False
-
- if prediction["IsAnomalous"] and prediction["Confidence"] >= confidence_limit:
- anomaly_types = {
- anomaly["Name"]
- for anomaly in prediction["Anomalies"]
- if anomaly["Name"] != "background"
- }
-
- if len(anomaly_types) > anomaly_types_limit:
- reject = True
- reject_info = (
- f"Rejected: Anomaly confidence ({prediction['Confidence']:.2%}) "
- f"is greater than limit ({confidence_limit:.2%}) and "
- f"the number of anomaly types ({len(anomaly_types)-1}) is "
- f"greater than the limit ({anomaly_types_limit})"
- )
-
- logger.info("%s", reject_info)
-
- if not reject:
- logger.info("No anomalies found.")
- return reject
-
- @staticmethod
- def reject_on_coverage(
- image, prediction, confidence_limit, anomaly_label, coverage_limit
- ):
- """
- Checks if the coverage area of an anomaly is greater than the coverage limit and if
- the prediction confidence is greater than the confidence limit.
- :param image: The name of the image file that was analyzed.
- :param prediction: The DetectAnomalyResult object returned from DetectAnomalies.
- :param confidence_limit: The minimum acceptable confidence (float 0-1).
- :anomaly_label: The anomaly label for the type of anomaly that you want to check.
- :coverage_limit: The maximum acceptable percentage coverage of an anomaly (float 0-1).
- :return: True if the error condition indicates an anomaly, otherwise False.
- """
-
- reject = False
-
- logger.info("Checking coverage for %s", image)
-
- if prediction["IsAnomalous"] and prediction["Confidence"] >= confidence_limit:
- for anomaly in prediction["Anomalies"]:
- if anomaly["Name"] == anomaly_label and anomaly["PixelAnomaly"][
- "TotalPercentageArea"
- ] > (coverage_limit):
- reject = True
- reject_info = (
- f"Rejected: Anomaly confidence ({prediction['Confidence']:.2%}) "
- f"is greater than limit ({confidence_limit:.2%}) and {anomaly['Name']} "
- f"coverage ({anomaly['PixelAnomaly']['TotalPercentageArea']:.2%}) "
- f"is greater than limit ({coverage_limit:.2%})"
- )
-
- logger.info("%s", reject_info)
-
- if not reject:
- logger.info("No anomalies found.")
-
- return reject
-
- @staticmethod
- def analyze_image(lookoutvision_client, image, config):
- """
- Analyzes an image with an Amazon Lookout for Vision model. Also
- runs a series of checks to determine if the contents of an image
- should be rejected.
- :param lookoutvision_client: A Lookout for Vision Boto3 client.
- param image: A local image that you want to analyze.
- param config: Configuration information for the model and reject
- limits.
- """
-
- project = config["project"]
- model_version = config["model_version"]
- confidence_limit = config["confidence_limit"]
- coverage_limit = config["coverage_limit"]
- anomaly_types_limit = config["anomaly_types_limit"]
- anomaly_label = config["anomaly_label"]
-
- # Get analysis results.
- print(f"Analyzing {image}.")
-
- prediction = Inference.detect_anomalies(
- lookoutvision_client, project, model_version, image
- )
-
- anomalies = []
-
- reject = Inference.reject_on_classification(image, prediction, confidence_limit)
-
- if reject:
- anomalies.append("Classification: An anomaly was found.")
-
- reject = Inference.reject_on_coverage(
- image, prediction, confidence_limit, anomaly_label, coverage_limit
- )
-
- if reject:
- anomalies.append("Coverage: Anomaly coverage too high.")
-
- reject = Inference.reject_on_anomaly_types(
- image, prediction, confidence_limit, anomaly_types_limit
- )
-
- if reject:
- anomalies.append("Anomaly type count: Too many anomaly types found.")
- print()
-
- if len(anomalies) > 0:
- print(f"Anomalies found in {image}")
- for anomaly in anomalies:
- print(f"{anomaly}")
- else:
- print(f"No anomalies found in {image}")
-
-
-def main():
- """
- Detects anomalies in an image file.
- """
- try:
- logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
-
- parser = argparse.ArgumentParser(
- description="Find anomalies with Amazon Lookout for Vision."
- )
- parser.add_argument(
- "image",
- help="The file that you want to analyze. Supply a local file path or a "
- "path to an S3 object.",
- )
- parser.add_argument(
- "config",
- help=(
- "The configuration JSON file to use. "
- "See https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/"
- "python/example_code/lookoutvision/README.md"
- ),
- )
-
- args = parser.parse_args()
-
- session = boto3.Session(profile_name="lookoutvision-access")
-
- lookoutvision_client = session.client("lookoutvision")
- s3_resource = session.resource("s3")
-
- # Get configuration information.
- with open(args.config, encoding="utf-8") as config_file:
- config = json.load(config_file)
-
- # Download image if located in S3 bucket.
- if args.image.startswith("s3://"):
- image = Inference.download_from_s3(s3_resource, args.image)
- else:
- image = args.image
-
- Inference.analyze_image(lookoutvision_client, image, config)
-
- # Delete image, if downloaded from S3 bucket.
- if args.image.startswith("s3://"):
- os.remove(image)
-
- except ClientError as err:
- print(f"Service error: {err.response['Error']['Message']}")
- except FileNotFoundError as err:
- print(f"The supplied file couldn't be found: {err.filename}.")
- except ValueError as err:
- print(f"A value error occurred: {err}.")
- else:
- print("\nSuccessfully completed analysis.")
-
-
-if __name__ == "__main__":
- main()
-# snippet-end:[python.example_code.lookoutvision.DetectAnomalies]
diff --git a/python/example_code/lookoutvision/models.py b/python/example_code/lookoutvision/models.py
deleted file mode 100644
index f6c2dc24947..00000000000
--- a/python/example_code/lookoutvision/models.py
+++ /dev/null
@@ -1,205 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Purpose
-
-Amazon Lookout for Vision model code examples used in the service documentation:
-https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/model.html
-
-Shows how to create and delete a model. Also, how to view the versions of the models
-in a project.
-"""
-
-import time
-import logging
-from botocore.exceptions import ClientError
-
-
-logger = logging.getLogger(__name__)
-
-
-# snippet-start:[python.example_code.lookoutvision.Models]
-class Models:
- # snippet-end:[python.example_code.lookoutvision.Models]
- """
- Provides example methods that create and manage Lookout for Vision models.
- """
-
- # snippet-start:[python.example_code.lookoutvision.CreateModel]
- @staticmethod
- def create_model(
- lookoutvision_client,
- project_name,
- training_results,
- tag_key=None,
- tag_key_value=None,
- ):
- """
- Creates a version of a Lookout for Vision model.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param project_name: The name of the project in which you want to create a
- model.
- :param training_results: The Amazon S3 location where training results are stored.
- :param tag_key: The key for a tag to add to the model.
- :param tag_key_value - A value associated with the tag_key.
- return: The model status and version.
- """
- try:
- logger.info("Training model...")
- output_bucket, output_folder = training_results.replace("s3://", "").split(
- "/", 1
- )
- output_config = {
- "S3Location": {"Bucket": output_bucket, "Prefix": output_folder}
- }
- tags = []
- if tag_key is not None:
- tags = [{"Key": tag_key, "Value": tag_key_value}]
-
- response = lookoutvision_client.create_model(
- ProjectName=project_name, OutputConfig=output_config, Tags=tags
- )
-
- logger.info("ARN: %s", response["ModelMetadata"]["ModelArn"])
- logger.info("Version: %s", response["ModelMetadata"]["ModelVersion"])
- logger.info("Started training...")
-
- print("Training started. Training might take several hours to complete.")
-
- # Wait until training completes.
- finished = False
- status = "UNKNOWN"
- while finished is False:
- model_description = lookoutvision_client.describe_model(
- ProjectName=project_name,
- ModelVersion=response["ModelMetadata"]["ModelVersion"],
- )
- status = model_description["ModelDescription"]["Status"]
-
- if status == "TRAINING":
- logger.info("Model training in progress...")
- time.sleep(600)
- continue
-
- if status == "TRAINED":
- logger.info("Model was successfully trained.")
- else:
- logger.info(
- "Model training failed: %s ",
- model_description["ModelDescription"]["StatusMessage"],
- )
- finished = True
- except ClientError:
- logger.exception("Couldn't train model.")
- raise
- else:
- return status, response["ModelMetadata"]["ModelVersion"]
-
- # snippet-end:[python.example_code.lookoutvision.CreateModel]
-
- # snippet-start:[python.example_code.lookoutvision.DescribeModel]
- @staticmethod
- def describe_model(lookoutvision_client, project_name, model_version):
- """
- Shows the performance metrics for a trained model.
-
- :param lookoutvision_client: A Boto3 Amazon Lookout for Vision client.
- :param project_name: The name of the project that contains the desired model.
- :param model_version: The version of the model.
- """
- response = lookoutvision_client.describe_model(
- ProjectName=project_name, ModelVersion=model_version
- )
- model_description = response["ModelDescription"]
- print(f"\tModel version: {model_description['ModelVersion']}")
- print(f"\tARN: {model_description['ModelArn']}")
- if "Description" in model_description:
- print(f"\tDescription: {model_description['Description']}")
- print(f"\tStatus: {model_description['Status']}")
- print(f"\tMessage: {model_description['StatusMessage']}")
- print(f"\tCreated: {str(model_description['CreationTimestamp'])}")
-
- if model_description["Status"] in ("TRAINED", "HOSTED"):
- training_start = model_description["CreationTimestamp"]
- training_end = model_description["EvaluationEndTimestamp"]
- duration = training_end - training_start
- print(f"\tTraining duration: {duration}")
-
- print("\n\tPerformance metrics\n\t-------------------")
- print(f"\tRecall: {model_description['Performance']['Recall']}")
- print(f"\tPrecision: {model_description['Performance']['Precision']}")
- print(f"\tF1: {model_description['Performance']['F1Score']}")
-
- training_output_bucket = model_description["OutputConfig"]["S3Location"][
- "Bucket"
- ]
- prefix = model_description["OutputConfig"]["S3Location"]["Prefix"]
- print(f"\tTraining output: s3://{training_output_bucket}/{prefix}")
-
- # snippet-end:[python.example_code.lookoutvision.DescribeModel]
-
- # snippet-start:[python.example_code.lookoutvision.ListModels]
- @staticmethod
- def describe_models(lookoutvision_client, project_name):
- """
- Gets information about all models in a Lookout for Vision project.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param project_name: The name of the project that you want to use.
- """
- try:
- response = lookoutvision_client.list_models(ProjectName=project_name)
- print("Project: " + project_name)
- for model in response["Models"]:
- Models.describe_model(
- lookoutvision_client, project_name, model["ModelVersion"]
- )
- print()
- print("Done...")
- except ClientError:
- logger.exception("Couldn't list models.")
- raise
-
- # snippet-end:[python.example_code.lookoutvision.ListModels]
-
- # snippet-start:[python.example_code.lookoutvision.DeleteModel]
- @staticmethod
- def delete_model(lookoutvision_client, project_name, model_version):
- """
- Deletes a Lookout for Vision model. The model must first be stopped and can't
- be in training.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param project_name: The name of the project that contains the desired model.
- :param model_version: The version of the model that you want to delete.
- """
- try:
- logger.info("Deleting model: %s", model_version)
- lookoutvision_client.delete_model(
- ProjectName=project_name, ModelVersion=model_version
- )
-
- model_exists = True
- while model_exists:
- response = lookoutvision_client.list_models(ProjectName=project_name)
-
- model_exists = False
- for model in response["Models"]:
- if model["ModelVersion"] == model_version:
- model_exists = True
-
- if model_exists is False:
- logger.info("Model deleted")
- else:
- logger.info("Model is being deleted...")
- time.sleep(2)
-
- logger.info("Deleted Model: %s", model_version)
- except ClientError:
- logger.exception("Couldn't delete model.")
- raise
-
-
-# snippet-end:[python.example_code.lookoutvision.DeleteModel]
diff --git a/python/example_code/lookoutvision/projects.py b/python/example_code/lookoutvision/projects.py
deleted file mode 100644
index 48924f9da9c..00000000000
--- a/python/example_code/lookoutvision/projects.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Purpose
-
-Amazon Lookout for Vision project code examples for using projects.
-Examples are used in the service documentation:
-https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/.
-
-Shows how to create and delete a project. Also, how to get information
-about your projects.
-"""
-
-import logging
-from botocore.exceptions import ClientError
-from models import Models
-
-
-logger = logging.getLogger(__name__)
-
-
-# snippet-start:[python.example_code.lookoutvision.Projects]
-class Projects:
- # snippet-end:[python.example_code.lookoutvision.Projects]
- """
- Provides example functions for creating, listing, and deleting Lookout for Vision
- projects
- """
-
- # snippet-start:[python.example_code.lookoutvision.CreateProject]
- @staticmethod
- def create_project(lookoutvision_client, project_name):
- """
- Creates a new Lookout for Vision project.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param project_name: The name for the new project.
- :return project_arn: The ARN of the new project.
- """
- try:
- logger.info("Creating project: %s", project_name)
- response = lookoutvision_client.create_project(ProjectName=project_name)
- project_arn = response["ProjectMetadata"]["ProjectArn"]
- logger.info("project ARN: %s", project_arn)
- except ClientError:
- logger.exception("Couldn't create project %s.", project_name)
- raise
- else:
- return project_arn
-
- # snippet-end:[python.example_code.lookoutvision.CreateProject]
-
- # snippet-start:[python.example_code.lookoutvision.DeleteProject]
- @staticmethod
- def delete_project(lookoutvision_client, project_name):
- """
- Deletes a Lookout for Vision Model
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param project_name: The name of the project that you want to delete.
- """
- try:
- logger.info("Deleting project: %s", project_name)
- response = lookoutvision_client.delete_project(ProjectName=project_name)
- logger.info("Deleted project ARN: %s ", response["ProjectArn"])
- except ClientError as err:
- logger.exception("Couldn't delete project %s.", project_name)
- raise
-
- # snippet-end:[python.example_code.lookoutvision.DeleteProject]
-
- # snippet-start:[python.example_code.lookoutvision.ListProjects]
- @staticmethod
- def list_projects(lookoutvision_client):
- """
- Lists information about the projects that are in in your AWS account
- and in the current AWS Region.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- """
- try:
- response = lookoutvision_client.list_projects()
- for project in response["Projects"]:
- print("Project: " + project["ProjectName"])
- print("\tARN: " + project["ProjectArn"])
- print("\tCreated: " + str(["CreationTimestamp"]))
- print("Datasets")
- project_description = lookoutvision_client.describe_project(
- ProjectName=project["ProjectName"]
- )
- if not project_description["ProjectDescription"]["Datasets"]:
- print("\tNo datasets")
- else:
- for dataset in project_description["ProjectDescription"][
- "Datasets"
- ]:
- print(f"\ttype: {dataset['DatasetType']}")
- print(f"\tStatus: {dataset['StatusMessage']}")
-
- print("Models")
- response_models = lookoutvision_client.list_models(
- ProjectName=project["ProjectName"]
- )
- if not response_models["Models"]:
- print("\tNo models")
- else:
- for model in response_models["Models"]:
- Models.describe_model(
- lookoutvision_client,
- project["ProjectName"],
- model["ModelVersion"],
- )
-
- print("------------------------------------------------------------\n")
- print("Done!")
- except ClientError:
- logger.exception("Problem listing projects.")
- raise
-
-
-# snippet-end:[python.example_code.lookoutvision.ListProjects]
diff --git a/python/example_code/lookoutvision/requirements.txt b/python/example_code/lookoutvision/requirements.txt
deleted file mode 100644
index 621e276912d..00000000000
--- a/python/example_code/lookoutvision/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-boto3>=1.26.79
-pytest>=7.2.1
diff --git a/python/example_code/lookoutvision/test.manifest b/python/example_code/lookoutvision/test.manifest
deleted file mode 100644
index feec4184d0b..00000000000
--- a/python/example_code/lookoutvision/test.manifest
+++ /dev/null
@@ -1,63 +0,0 @@
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-1.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T20:52:51.851Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 13:52:52 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-1.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-2.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:11:39.545Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:11:40 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-2.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-3.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:26:25.375Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:26:25 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-3.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-4.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:42:06.772Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:42:07 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-4.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-5.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:44:53.826Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:44:54 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-5.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-6.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:46:04.389Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:46:04 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-6.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-7.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:47:56.782Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:47:57 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-7.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-8.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T20:54:44.223Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 13:54:45 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-8.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-9.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T20:55:56.511Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 13:55:57 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-9.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-10.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T20:56:51.756Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 13:56:52 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-10.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-11.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T20:58:24.882Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 13:58:25 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-11.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-12.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:00:17.391Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:00:18 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-12.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-13.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:01:47.230Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:01:47 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-13.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-14.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:03:10.957Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:03:11 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-14.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-15.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:04:26.254Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:04:26 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-15.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-16.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:08:11.436Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:08:12 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-16.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-17.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:09:23.146Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:09:23 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-17.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-18.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:12:53.171Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:12:53 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-18.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-19.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:14:15.312Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:14:15 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-19.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-20.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:16:34.423Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:16:35 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-20.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-21.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:18:27.148Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:18:27 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-21.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-22.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:21:04.105Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:21:04 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-22.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-23.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:22:38.603Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:22:39 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-23.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-24.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:25:06.358Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:25:07 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-24.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-25.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:27:10.037Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:27:10 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-25.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-26.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:29:10.656Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:29:11 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-26.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-27.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:31:23.022Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:31:23 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-27.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-28.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:34:09.080Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:34:09 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-28.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-29.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:35:21.697Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:35:22 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-29.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-30.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:36:33.845Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:36:34 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-30.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-31.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:37:34.626Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:37:35 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-31.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/anomaly-32.jpg", "anomaly-label-metadata": {"job-name": "anomaly-label", "class-name": "anomaly", "human-annotated": "yes", "creation-date": "2022-08-22T21:43:49.681Z", "type": "groundtruth/image-classification"}, "anomaly-label": 1, "anomaly-mask-ref-metadata": {"internal-color-map": {"0": {"class-name": "cracked", "hex-color": "#23A436"}}, "job-name": "labeling-job/object-mask-ref", "human-annotated": "yes", "creation-date": "Mon Aug 22 2022 14:43:50 GMT-0700 (Pacific Daylight Time)", "type": "groundtruth/semantic-segmentation"}, "anomaly-mask-ref": "s3://lfv-getting-started/export21/test/masks/export8/masks/anomaly-32.png"}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-1.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.427", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-2.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.427", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-3.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.427", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-4.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.427", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-5.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.428", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-6.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.428", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-7.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.428", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-8.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.428", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-9.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.428", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-10.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.429", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-11.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.429", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-12.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.429", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-13.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.429", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-14.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.429", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-15.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.430", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-16.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.430", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-17.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.430", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-18.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.430", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-19.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.430", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-20.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.430", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-21.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.431", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-22.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.431", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-23.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.431", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-24.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.431", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-25.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.431", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-26.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.432", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-27.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.432", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-28.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.432", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-29.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.432", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-30.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.432", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
-{"source-ref": "s3://lfv-getting-started/export21/test/images/export8/train/export/train/test-5/training-images/normal-31.jpg", "anomaly-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "normal", "human-annotated": "yes", "creation-date": "2022-08-22T20:49:51.426", "type": "groundtruth/image-classification"}, "anomaly-label": 0}
diff --git a/python/example_code/lookoutvision/test/__init__.py b/python/example_code/lookoutvision/test/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/python/example_code/lookoutvision/test/conftest.py b/python/example_code/lookoutvision/test/conftest.py
deleted file mode 100644
index d0236963531..00000000000
--- a/python/example_code/lookoutvision/test/conftest.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Contains common test fixtures used to run unit tests.
-"""
-
-import random
-import sys
-
-# This is needed so Python can find test_tools on the path.
-sys.path.append("../..")
-from test_tools.fixtures.common import *
diff --git a/python/example_code/lookoutvision/test/test_csv_to_manifest.py b/python/example_code/lookoutvision/test/test_csv_to_manifest.py
deleted file mode 100644
index c8b8f7dee5b..00000000000
--- a/python/example_code/lookoutvision/test/test_csv_to_manifest.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-from csv_to_manifest import check_errors, create_manifest_file
-from os.path import exists
-from os import remove
-from os import path
-import pytest
-
-"""
-Unit tests for csv_to_manifest.py.
-"""
-
-
-def clean_up(*argv):
- """
- Deletes supplied files, if they exist.
- Removes any previous test run files.
- """
- for arg in argv:
- if exists(arg):
- remove(arg)
-
-
-@pytest.mark.parametrize(
- "csv_file, result", [("test/test_csvs/test_s3_supplied.csv", False)]
-)
-def test_check_no_errors(csv_file, result):
- """
- Checks that the CSV file is valid.
- """
-
- errors_file = f"{path.splitext(csv_file)[0]}_errors.csv"
- deduplicated_file = f"{path.splitext(csv_file)[0]}_deduplicated.csv"
- manifest_file = f"{path.splitext(csv_file)[0]}.manifest"
-
- clean_up(deduplicated_file, errors_file, manifest_file)
-
- assert check_errors(csv_file) == result
- assert not exists(deduplicated_file)
- assert not exists(errors_file)
-
- clean_up(deduplicated_file, errors_file, manifest_file)
-
-
-@pytest.mark.parametrize(
- "csv_file,result", [("test/test_csvs/test_dups_errors.csv", True)]
-)
-def test_check_errors(csv_file, result):
- """
- Checks that a CSV file with duplications and classification
- errors creates the deduplication and errors CSV file.
- """
-
- errors_file = f"{path.splitext(csv_file)[0]}_errors.csv"
- deduplicated_file = f"{path.splitext(csv_file)[0]}_deduplicated.csv"
- manifest_file = f"{path.splitext(csv_file)[0]}.manifest"
-
- clean_up(deduplicated_file, errors_file, manifest_file)
-
- assert check_errors(csv_file) == result
- assert exists(deduplicated_file)
- assert exists(errors_file)
- assert not exists(manifest_file)
-
- clean_up(deduplicated_file, errors_file, manifest_file)
-
-
-@pytest.mark.parametrize(
- "csv_file,img_count,anom_count", [("test/test_csvs/test_s3_supplied.csv", 9, 5)]
-)
-def test_create_manifest_s3_supplied(csv_file, img_count, anom_count):
- """
- Checks that a CSV file with images and an Amazon S3 path creates
- a manifest file.
- """
-
- s3_path = "s3://docexamplebucket1/circuitboard/train/"
- errors_file = f"{path.splitext(csv_file)[0]}_errors.csv"
- deduplicated_file = f"{path.splitext(csv_file)[0]}_deduplicated.csv"
- manifest_file = f"{path.splitext(csv_file)[0]}.manifest"
-
- clean_up(deduplicated_file, errors_file, manifest_file)
-
- image_count, anomalous_count = create_manifest_file(
- csv_file, manifest_file, s3_path
- )
- assert image_count == img_count
- assert anomalous_count == anom_count
- assert exists(manifest_file)
- assert not exists(deduplicated_file)
- assert not exists(errors_file)
-
- clean_up(deduplicated_file, errors_file, manifest_file)
-
-
-@pytest.mark.parametrize(
- "csv_file,img_count,anom_count", [("test/test_csvs/test_no_s3.csv", 7, 4)]
-)
-def test_create_manifest_no_s3_supplied(csv_file, img_count, anom_count):
- """
- Checks that a CSV file with images and no Amazon S3 path creates
- a manifest file.
- """
-
- s3_path = ""
- errors_file = f"{path.splitext(csv_file)[0]}_errors.csv"
- deduplicated_file = f"{path.splitext(csv_file)[0]}_deduplicated.csv"
- manifest_file = f"{path.splitext(csv_file)[0]}.manifest"
-
- clean_up(deduplicated_file, errors_file, manifest_file)
-
- image_count, anomalous_count = create_manifest_file(
- csv_file, manifest_file, s3_path
- )
- assert image_count == img_count
- assert anomalous_count == anom_count
- assert exists(manifest_file)
- assert not exists(deduplicated_file)
- assert not exists(errors_file)
-
- clean_up(deduplicated_file, errors_file, manifest_file)
diff --git a/python/example_code/lookoutvision/test/test_csvs/test_dups_errors.csv b/python/example_code/lookoutvision/test/test_csvs/test_dups_errors.csv
deleted file mode 100644
index ac3f2cbbf77..00000000000
--- a/python/example_code/lookoutvision/test/test_csvs/test_dups_errors.csv
+++ /dev/null
@@ -1,13 +0,0 @@
-s3://docexamplebucket1/circuitboard/train/anomaly/train-anomaly_1.jpg,anomaly
-s3://docexamplebucket1/circuitboard/train/anomaly/train-anomaly_10.jpg,anomaly
-s3://docexamplebucket1/circuitboard/train/anomaly/train-anomaly_10.jpg,anomalous
-s3://docexamplebucket1/circuitboard/train/anomaly/train-anomaly_11.jpg,anomalous
-
-s3://docexamplebucket1/circuitboard/train/normal/train-normal_1.jpg,normal
-s3://docexamplebucket1/circuitboard/train/normal/train-normal_10.jpg,normal
-s3://docexamplebucket1/circuitboard/train/normal/train-normal_10.jpg,normal
-s3://docexamplebucket1/circuitboard/train/normal/train-normal_11.jpg,correct
-
-
-
-
diff --git a/python/example_code/lookoutvision/test/test_csvs/test_no_s3.csv b/python/example_code/lookoutvision/test/test_csvs/test_no_s3.csv
deleted file mode 100644
index 32b60977ae9..00000000000
--- a/python/example_code/lookoutvision/test/test_csvs/test_no_s3.csv
+++ /dev/null
@@ -1,11 +0,0 @@
-train-anomaly_1.jpg,anomaly
-train-anomaly_10.jpg,anomaly
-train-anomaly_11.jpg,anomaly
-train-anomaly_12.jpg,anomaly
-train-normal_1.jpg,normal
-train-normal_10.jpg,normal
-train-normal_11.jpg,normal
-
-
-
-
diff --git a/python/example_code/lookoutvision/test/test_csvs/test_s3_supplied.csv b/python/example_code/lookoutvision/test/test_csvs/test_s3_supplied.csv
deleted file mode 100644
index 9dd8d10e4e4..00000000000
--- a/python/example_code/lookoutvision/test/test_csvs/test_s3_supplied.csv
+++ /dev/null
@@ -1,13 +0,0 @@
-s3://docexamplebucket1/circuitboard/train/anomaly/train-anomaly_1.jpg,anomaly
-s3://docexamplebucket1/circuitboard/train/anomaly/train-anomaly_10.jpg,anomaly
-s3://docexamplebucket1/circuitboard/train/anomaly/train-anomaly_11.jpg,anomaly
-s3://docexamplebucket1/circuitboard/train/anomaly/train-anomaly_12.jpg,anomaly
-s3://docexamplebucket1/circuitboard/train/anomaly/train-anomaly_13.jpg,anomaly
-s3://docexamplebucket1/circuitboard/train/normal/train-normal_1.jpg,normal
-s3://docexamplebucket1/circuitboard/train/normal/train-normal_10.jpg,normal
-s3://docexamplebucket1/circuitboard/train/normal/train-normal_11.jpg,normal
-s3://docexamplebucket1/circuitboard/train/normal/train-normal_12.jpg,normal
-
-
-
-
diff --git a/python/example_code/lookoutvision/test/test_datasets.py b/python/example_code/lookoutvision/test/test_datasets.py
deleted file mode 100644
index 52ac395c203..00000000000
--- a/python/example_code/lookoutvision/test/test_datasets.py
+++ /dev/null
@@ -1,168 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Unit tests for datasets.py.
-"""
-
-import boto3
-from botocore.exceptions import ClientError
-import pytest
-
-from datasets import Datasets
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_create_dataset(make_stubber, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- bucket = "test-bucket"
- object_key = "test-object"
- manifest_file = f"{bucket}/{object_key}"
- dataset_type = "train"
- status = "CREATE_COMPLETE"
- message = "Test message"
-
- lookoutvision_stubber.stub_create_dataset(
- project_name,
- dataset_type,
- bucket,
- object_key,
- status,
- message,
- error_code=error_code,
- )
- if error_code is None:
- lookoutvision_stubber.stub_describe_dataset(
- project_name, dataset_type, status, message
- )
-
- if error_code is None:
- Datasets.create_dataset(
- lookoutvision_client, project_name, manifest_file, dataset_type
- )
- else:
- with pytest.raises(ClientError) as exc_info:
- Datasets.create_dataset(
- lookoutvision_client, project_name, manifest_file, dataset_type
- )
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_create_manifest_file_s3(make_stubber, monkeypatch, error_code):
- s3_resource = boto3.resource("s3")
- s3_stubber = make_stubber(s3_resource.meta.client)
- image_bucket = "image-bucket"
- image_prefix = "image-prefix/"
- image_path = f"{image_bucket}/{image_prefix}"
- mani_bucket = "mani-bucket"
- mani_prefix = "mani-prefix/"
- manifest_path = f"{mani_bucket}/{mani_prefix}"
-
- monkeypatch.setattr(
- s3_resource.meta.client,
- "upload_file",
- lambda Filename, Bucket, Key, ExtraArgs, Callback, Config: None,
- )
-
- s3_stubber.stub_list_objects(
- image_bucket,
- [f"{image_prefix}anomaly/anomaly-test-key"],
- f"{image_prefix}anomaly/",
- "/",
- )
- s3_stubber.stub_list_objects(
- image_bucket,
- [f"{image_prefix}normal/normal-test-key"],
- f"{image_prefix}normal/",
- "/",
- error_code=error_code,
- )
-
- with open("temp.manifest", "w") as mani:
- mani.write("Test manifest.")
-
- if error_code is None:
- Datasets.create_manifest_file_s3(s3_resource, image_path, manifest_path)
- else:
- with pytest.raises(ClientError) as exc_info:
- Datasets.create_manifest_file_s3(s3_resource, image_path, manifest_path)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_delete_dataset(make_stubber, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- dataset_type = "train"
-
- lookoutvision_stubber.stub_delete_dataset(
- project_name, dataset_type, error_code=error_code
- )
-
- if error_code is None:
- Datasets.delete_dataset(lookoutvision_client, project_name, dataset_type)
- else:
- with pytest.raises(ClientError) as exc_info:
- Datasets.delete_dataset(lookoutvision_client, project_name, dataset_type)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_describe_dataset(make_stubber, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- dataset_type = "train"
- status = "CREATE_COMPLETE"
- message = "Test message"
- image_stats = {"Total": 5, "Labeled": 2, "Normal": 2, "Anomaly": 1}
-
- lookoutvision_stubber.stub_describe_dataset(
- project_name, dataset_type, status, message, image_stats, error_code=error_code
- )
-
- if error_code is None:
- Datasets.describe_dataset(lookoutvision_client, project_name, dataset_type)
- else:
- with pytest.raises(ClientError) as exc_info:
- Datasets.describe_dataset(lookoutvision_client, project_name, dataset_type)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_update_dataset_entries(make_stubber, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- updates_file = "test/test_manifests/updates.manifest"
- dataset_type = "train"
- status_complete = "UPDATE_COMPLETE"
- status_running = "UPDATE_IN_PROGRESS"
- message = "Test message"
- changes = ""
-
- with open(updates_file) as f:
- changes = f.read()
-
- lookoutvision_stubber.stub_update_dataset_entries(
- project_name, dataset_type, changes, status_running, error_code=error_code
- )
- if error_code is None:
- lookoutvision_stubber.stub_describe_dataset(
- project_name, dataset_type, status_complete, message
- )
-
- if error_code is None:
- Datasets.update_dataset_entries(
- lookoutvision_client, project_name, dataset_type, updates_file
- )
- else:
- with pytest.raises(ClientError) as exc_info:
- Datasets.update_dataset_entries(
- lookoutvision_client, project_name, dataset_type, updates_file
- )
- assert exc_info.value.response["Error"]["Code"] == error_code
diff --git a/python/example_code/lookoutvision/test/test_export_datasets.py b/python/example_code/lookoutvision/test/test_export_datasets.py
deleted file mode 100644
index 8b36d8651d4..00000000000
--- a/python/example_code/lookoutvision/test/test_export_datasets.py
+++ /dev/null
@@ -1,270 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Unit tests for export_datasets.py.
-"""
-
-import boto3
-from botocore.exceptions import ClientError
-import pytest
-
-from export_datasets import export_datasets
-from export_datasets import copy_file
-from export_datasets import upload_manifest_file
-from export_datasets import get_dataset_types
-from export_datasets import process_json_line
-from export_datasets import write_manifest_file
-
-
-@pytest.mark.parametrize(
- "error_code,stop_on_method",
- [
- (None, None),
- ("TestException", "stub_describe_project"),
- ("TestException", "stub_list_dataset_entries"),
- ("TestException", "stub_copy_object"),
- ("TestPutException", "stub_put_object"),
- ],
-)
-def test_export_datasets(make_stubber, stub_runner, error_code, stop_on_method):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project"
- s3_path = "s3://dest-bucket/stubber_test/"
- dataset_type = "train"
- json_lines_file = "test/test_manifests/updates.manifest"
-
- dataset = {
- "DatasetType": "train",
- "Status": "CREATE_COMPLETE",
- "StatusMessage": "The model is hosted.",
- }
-
- s3_resource = boto3.resource("s3")
- s3_stubber = make_stubber(s3_resource.meta.client)
- src_bucket_name = "bucket"
- src_key = "cookies/Anomaly/anomaly-1.jpg"
- dest_bucket_name = "dest-bucket"
- dest_key = "stubber_test/train/images/cookies/Anomaly/anomaly-1.jpg"
- manifest_key = "stubber_test/datasets/train.manifest"
-
- with open(json_lines_file, encoding="utf-8") as json_file:
- json_lines = json_file.read()
-
- with stub_runner(error_code, stop_on_method) as runner:
- runner.add(lookoutvision_stubber.stub_describe_project, project_name, [dataset])
- runner.add(
- lookoutvision_stubber.stub_list_dataset_entries,
- project_name,
- dataset_type,
- json_lines,
- )
- runner.add(
- s3_stubber.stub_copy_object,
- src_bucket_name,
- src_key,
- dest_bucket_name,
- dest_key,
- )
- if error_code is None or error_code == "TestPutException":
- runner.add(s3_stubber.stub_head_object, dest_bucket_name, dest_key)
- runner.add(s3_stubber.stub_put_object, dest_bucket_name, manifest_key)
- if error_code is None:
- runner.add(s3_stubber.stub_head_object, dest_bucket_name, manifest_key)
-
- if error_code is None:
- export_datasets(lookoutvision_client, s3_resource, project_name, s3_path)
- else:
- with pytest.raises(ClientError) as exc_info:
- export_datasets(lookoutvision_client, s3_resource, project_name, s3_path)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize(
- "error_code,stop_on_method", [(None, None), ("TestException", "stub_copy_object")]
-)
-def test_copy_file(make_stubber, stub_runner, error_code, stop_on_method):
- s3_resource = boto3.resource("s3")
- s3_stubber = make_stubber(s3_resource.meta.client)
- source_file = "s3://bucket/folder/image.jpg"
- destination_file = "s3://bucket2/folder/image.jpg"
- src_bucket_name = "bucket"
- src_key = "folder/image.jpg"
- dest_bucket_name = "bucket2"
- dest_key = "folder/image.jpg"
-
- with stub_runner(error_code, stop_on_method) as runner:
- runner.add(
- s3_stubber.stub_copy_object,
- src_bucket_name,
- src_key,
- dest_bucket_name,
- dest_key,
- )
- if error_code is None:
- runner.add(s3_stubber.stub_head_object, dest_bucket_name, dest_key)
-
- if error_code is None:
- copy_file(s3_resource, source_file, destination_file)
- else:
- with pytest.raises(ClientError) as exc_info:
- copy_file(s3_resource, source_file, destination_file)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize(
- "error_code,stop_on_method", [(None, None), ("TestException", "stub_put_object")]
-)
-def test_upload_manifest_file(make_stubber, stub_runner, error_code, stop_on_method):
- s3_resource = boto3.resource("s3")
- s3_stubber = make_stubber(s3_resource.meta.client)
-
- dest_bucket_name = "dest-bucket"
- manifest_folder = "stubber_test/datasets/"
- manifest_file = "train.manifest"
- destination = f"s3://{dest_bucket_name}/{manifest_folder}/"
-
- with stub_runner(error_code, stop_on_method) as runner:
- runner.add(
- s3_stubber.stub_put_object,
- dest_bucket_name,
- manifest_folder + "/" + manifest_file,
- )
- if error_code is None:
- runner.add(
- s3_stubber.stub_head_object,
- dest_bucket_name,
- manifest_folder + "/" + manifest_file,
- )
-
- if error_code is None:
- upload_manifest_file(s3_resource, manifest_file, destination)
- else:
- with pytest.raises(ClientError) as exc_info:
- upload_manifest_file(s3_resource, manifest_file, destination)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize(
- "error_code,stop_on_method",
- [(None, None), ("TestException", "stub_describe_project")],
-)
-def test_get_dataset_types(make_stubber, stub_runner, error_code, stop_on_method):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project"
-
- dataset = {
- "DatasetType": "train",
- "Status": "CREATE_COMPLETE",
- "StatusMessage": "The model is hosted.",
- }
-
- with stub_runner(error_code, stop_on_method) as runner:
- runner.add(lookoutvision_stubber.stub_describe_project, project_name, [dataset])
-
- if error_code is None:
- get_dataset_types(lookoutvision_client, project_name)
- else:
- with pytest.raises(ClientError) as exc_info:
- get_dataset_types(lookoutvision_client, project_name)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize(
- "error_code,stop_on_method", [(None, None), ("TestException", "stub_copy_object")]
-)
-def test_process_json_line(make_stubber, stub_runner, error_code, stop_on_method):
- s3_resource = boto3.resource("s3")
- s3_stubber = make_stubber(s3_resource.meta.client)
-
- destination_folder = "s3://bucket2/folder/"
- src_bucket_name = "bucket"
- src_key = "cookies/Anomaly/anomaly-1.jpg"
- dest_bucket_name = "dest-bucket"
- dest_key = "files/train/images/cookies/Anomaly/anomaly-1.jpg"
- destination_folder = f"s3://{dest_bucket_name}/files/"
-
- json_lines_file = "test/test_manifests/updates.manifest"
-
- with open(json_lines_file, encoding="utf-8") as json_file:
- json_line = json_file.read()
-
- with stub_runner(error_code, stop_on_method) as runner:
- runner.add(
- s3_stubber.stub_copy_object,
- src_bucket_name,
- src_key,
- dest_bucket_name,
- dest_key,
- )
- if error_code is None:
- runner.add(s3_stubber.stub_head_object, dest_bucket_name, dest_key)
-
- if error_code is None:
- process_json_line(s3_resource, json_line, "train", destination_folder)
- else:
- with pytest.raises(ClientError) as exc_info:
- process_json_line(s3_resource, json_line, "train", destination_folder)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize(
- "error_code,stop_on_method",
- [
- (None, None),
- ("TestException", "stub_list_dataset_entries"),
- ("TestException", "stub_copy_object"),
- ("TestPutException", "stub_put_object"),
- ],
-)
-def test_write_manifest_file(make_stubber, stub_runner, error_code, stop_on_method):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project"
- s3_path = "s3://dest-bucket/stubber_test/"
- dataset_type = "train"
- json_lines_file = "test/test_manifests/updates.manifest"
-
- s3_resource = boto3.resource("s3")
- s3_stubber = make_stubber(s3_resource.meta.client)
- src_bucket_name = "bucket"
- src_key = "cookies/Anomaly/anomaly-1.jpg"
- dest_bucket_name = "dest-bucket"
- dest_key = "stubber_test/train/images/cookies/Anomaly/anomaly-1.jpg"
- manifest_key = "stubber_test/datasets/train.manifest"
-
- with open(json_lines_file, encoding="utf-8") as json_file:
- json_lines = json_file.read()
-
- with stub_runner(error_code, stop_on_method) as runner:
- runner.add(
- lookoutvision_stubber.stub_list_dataset_entries,
- project_name,
- dataset_type,
- json_lines,
- )
- runner.add(
- s3_stubber.stub_copy_object,
- src_bucket_name,
- src_key,
- dest_bucket_name,
- dest_key,
- )
- if error_code is None or error_code == "TestPutException":
- runner.add(s3_stubber.stub_head_object, dest_bucket_name, dest_key)
- runner.add(s3_stubber.stub_put_object, dest_bucket_name, manifest_key)
- if error_code is None:
- runner.add(s3_stubber.stub_head_object, dest_bucket_name, manifest_key)
-
- if error_code is None:
- write_manifest_file(
- lookoutvision_client, s3_resource, project_name, "train", s3_path
- )
- else:
- with pytest.raises(ClientError) as exc_info:
- write_manifest_file(
- lookoutvision_client, s3_resource, project_name, "train", s3_path
- )
- assert exc_info.value.response["Error"]["Code"] == error_code
diff --git a/python/example_code/lookoutvision/test/test_find_running_models.py b/python/example_code/lookoutvision/test/test_find_running_models.py
deleted file mode 100644
index 9c6e9db91b2..00000000000
--- a/python/example_code/lookoutvision/test/test_find_running_models.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Unit tests for find_running_models.py.
-"""
-
-import pytest
-from botocore.exceptions import ClientError
-import datetime
-import boto3
-import models
-from boto3.session import Session
-
-from find_running_models import find_running_models, find_running_models_in_project
-
-
-@pytest.mark.parametrize(
- "error_code,stop_on_method",
- [
- (None, None),
- ("TestException", "stub_list_models"),
- ("TestException", "stub_describe_model"),
- ],
-)
-def test_find_models_in_project(make_stubber, stub_runner, error_code, stop_on_method):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- model = "test-model"
- model_version = "test-model"
- model_arn = "test-arn"
- description = "test description"
- status = "HOSTED"
- message = "Test message!"
- created = datetime.datetime.now()
- trained = created + datetime.timedelta(minutes=10)
- recall = 0.3
- precision = 0.5
- f1 = 0.7
- out_buck = "amzn-s3-demo-bucket"
- out_folder = "test-folder"
-
- with stub_runner(error_code, stop_on_method) as runner:
- runner.add(lookoutvision_stubber.stub_list_models, project_name, [model])
- runner.add(
- lookoutvision_stubber.stub_describe_model,
- project_name,
- model_version,
- model_arn,
- status,
- {
- "description": description,
- "message": message,
- "created": created,
- "trained": trained,
- "recall": recall,
- "precision": precision,
- "f1": f1,
- "out_bucket": out_buck,
- "out_folder": out_folder,
- },
- )
-
- if error_code is None:
- running_models = find_running_models_in_project(
- lookoutvision_client, project_name
- )
- assert len(running_models) == 1
- else:
- with pytest.raises(ClientError) as exc_info:
- find_running_models_in_project(lookoutvision_client, project_name)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize(
- "error_code,stop_on_method",
- [
- (None, None),
- ("TestException", "stub_list_projects"),
- ("TestException", "stub_list_models"),
- ("TestException", "stub_describe_model"),
- ],
-)
-def test_find_running_models(
- make_stubber, stub_runner, monkeypatch, error_code, stop_on_method
-):
- boto3_session = boto3.Session()
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- model = "test-model"
- model_version = "test-model"
- model_arn = "test-arn"
- description = "test description"
- status = "HOSTED"
- message = "Test message!"
- created = datetime.datetime.now()
- trained = created + datetime.timedelta(minutes=10)
- recall = 0.3
- precision = 0.5
- f1 = 0.7
- out_buck = "amzn-s3-demo-bucket"
- out_folder = "test-folder"
- project_arn = "test-arn"
- region = "us-east-1"
-
- monkeypatch.setattr(
- boto3_session, "client", lambda c, region_name: lookoutvision_client
- )
- # monkeypatch.setattr(Session, 'profile_name', 'lookoutvision-access')
-
- # Patch AWS Region list
- monkeypatch.setattr(
- boto3_session, "get_available_regions", lambda service_name: [region]
- )
- # Patch lookoutvision client to manage multiple AWS Region clients.
- # monkeypatch.setattr(boto3, 'client', get_boto_entity)
-
- # Set up stubbed calls needed to mock getting running models.
- with stub_runner(error_code, stop_on_method) as runner:
- runner.add(
- lookoutvision_stubber.stub_list_projects,
- [project_name],
- [{"arn": project_arn, "created": created}],
- )
- runner.add(lookoutvision_stubber.stub_list_models, project_name, [model])
- runner.add(
- lookoutvision_stubber.stub_describe_model,
- project_name,
- model_version,
- model_arn,
- status,
- {
- "description": description,
- "message": message,
- "created": created,
- "trained": trained,
- "recall": recall,
- "precision": precision,
- "f1": f1,
- "out_bucket": out_buck,
- "out_folder": out_folder,
- },
- )
-
- if error_code is None:
- running_models = find_running_models(boto3_session)
- assert len(running_models) == 1
- else:
- with pytest.raises(ClientError) as exc_info:
- find_running_models(boto3_session)
- assert exc_info.value.response["Error"]["Code"] == error_code
diff --git a/python/example_code/lookoutvision/test/test_find_tag.py b/python/example_code/lookoutvision/test/test_find_tag.py
deleted file mode 100644
index b7812fd41ca..00000000000
--- a/python/example_code/lookoutvision/test/test_find_tag.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Unit tests for find_tag.py.
-"""
-
-import boto3
-from botocore.exceptions import ClientError
-import pytest
-
-import find_tag
-
-
-@pytest.mark.parametrize(
- "error_code,stop_on_method",
- [
- (None, None),
- ("TestException", "stub_list_projects"),
- ("TestException", "stub_list_models"),
- ("TestException", "stub_describe_model"),
- ("TestException", "stub_list_tags_for_resource"),
- ],
-)
-def test_find_tag_in_projects(make_stubber, stub_runner, error_code, stop_on_method):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project"
- model_version = "test-model"
- model_arn = "test-arn"
- key = "test-key"
- value = "test-value"
-
- with stub_runner(error_code, stop_on_method) as runner:
- runner.add(lookoutvision_stubber.stub_list_projects, [project_name])
- runner.add(
- lookoutvision_stubber.stub_list_models, project_name, [model_version]
- )
- runner.add(
- lookoutvision_stubber.stub_describe_model,
- project_name,
- model_version,
- model_arn,
- )
- runner.add(
- lookoutvision_stubber.stub_list_tags_for_resource, model_arn, {key: value}
- )
-
- if error_code is None:
- got_project = find_tag.find_tag_in_projects(lookoutvision_client, key, value)
- assert got_project == [{"Project": project_name, "ModelVersion": model_version}]
- else:
- with pytest.raises(ClientError) as exc_info:
- find_tag.find_tag_in_projects(lookoutvision_client, key, value)
- assert exc_info.value.response["Error"]["Code"] == error_code
diff --git a/python/example_code/lookoutvision/test/test_hello.py b/python/example_code/lookoutvision/test/test_hello.py
deleted file mode 100644
index ef8cd77a03a..00000000000
--- a/python/example_code/lookoutvision/test/test_hello.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Unit tests for projects.py.
-"""
-
-import datetime
-import boto3
-from botocore.exceptions import ClientError
-import pytest
-
-from hello import Hello
-
-
-@pytest.mark.parametrize(
- "error_code,stop_on_method", [(None, None), ("TestException", "stub_list_projects")]
-)
-def test_hello(make_stubber, stub_runner, error_code, stop_on_method):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project"
- project_arn = "test-arn"
- created = datetime.datetime.now()
- model_version = "test-model"
- dataset = {"DatasetType": "testing", "StatusMessage": "nicely tested"}
-
- with stub_runner(error_code, stop_on_method) as runner:
- runner.add(
- lookoutvision_stubber.stub_list_projects,
- [project_name],
- [{"arn": project_arn, "created": created}],
- )
-
- if error_code is None:
- Hello.list_projects(lookoutvision_client)
- else:
- with pytest.raises(ClientError) as exc_info:
- Hello.list_projects(lookoutvision_client)
- assert exc_info.value.response["Error"]["Code"] == error_code
diff --git a/python/example_code/lookoutvision/test/test_hosting.py b/python/example_code/lookoutvision/test/test_hosting.py
deleted file mode 100644
index ff99ef9cbe6..00000000000
--- a/python/example_code/lookoutvision/test/test_hosting.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Unit tests for hosting.py.
-"""
-
-import boto3
-from botocore.exceptions import ClientError
-import pytest
-
-from hosting import Hosting
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_start_model(make_stubber, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- model_version = "test-model"
- min_units = 3
-
- lookoutvision_stubber.stub_start_model(project_name, model_version, min_units)
- lookoutvision_stubber.stub_describe_model(
- project_name, model_version, "test-arn", "HOSTED", error_code=error_code
- )
-
- if error_code is None:
- Hosting.start_model(
- lookoutvision_client, project_name, model_version, min_units
- )
- else:
- with pytest.raises(ClientError) as exc_info:
- Hosting.start_model(
- lookoutvision_client, project_name, model_version, min_units
- )
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_stop_model(make_stubber, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- model_version = "test-model"
-
- lookoutvision_stubber.stub_stop_model(
- project_name, model_version, "STOPPING_HOSTING"
- )
- lookoutvision_stubber.stub_describe_model(
- project_name, model_version, "test-arn", "TRAINED", error_code=error_code
- )
-
- if error_code is None:
- Hosting.stop_model(lookoutvision_client, project_name, model_version)
- else:
- with pytest.raises(ClientError) as exc_info:
- Hosting.stop_model(lookoutvision_client, project_name, model_version)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize(
- "error_code,stop_on_method",
- [
- (None, None),
- ("TestException", "stub_list_projects"),
- ("TestException", "stub_list_models"),
- ("TestException", "stub_describe_model"),
- ],
-)
-def test_list_hosted(make_stubber, stub_runner, error_code, stop_on_method):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project"
- model_version = "test-model"
- model_arn = "test-arn"
- status = "HOSTED"
-
- with stub_runner(error_code, stop_on_method) as runner:
- runner.add(lookoutvision_stubber.stub_list_projects, [project_name])
- runner.add(
- lookoutvision_stubber.stub_list_models, project_name, [model_version]
- )
- runner.add(
- lookoutvision_stubber.stub_describe_model,
- project_name,
- model_version,
- model_arn,
- status,
- )
-
- if error_code is None:
- Hosting.list_hosted(lookoutvision_client)
- else:
- with pytest.raises(ClientError) as exc_info:
- Hosting.list_hosted(lookoutvision_client)
- assert exc_info.value.response["Error"]["Code"] == error_code
diff --git a/python/example_code/lookoutvision/test/test_inference.py b/python/example_code/lookoutvision/test/test_inference.py
deleted file mode 100644
index 1451e3768e5..00000000000
--- a/python/example_code/lookoutvision/test/test_inference.py
+++ /dev/null
@@ -1,151 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Unit tests for inference.py.
-"""
-
-import imghdr
-from unittest.mock import patch, mock_open
-import boto3
-from botocore.exceptions import ClientError
-import pytest
-
-from inference import Inference
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_detect_anomalies(make_stubber, monkeypatch, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- model_version = "test-model"
- photo = "test.jpeg"
- content_type = "image/jpeg"
- image_contents = b"test-contents"
- anomalous = True
- confidence = 0.5
-
- monkeypatch.setattr(imghdr, "what", lambda f: "jpeg")
-
- lookoutvision_stubber.stub_detect_anomalies(
- project_name,
- model_version,
- content_type,
- image_contents,
- anomalous,
- confidence,
- error_code=error_code,
- )
-
- if error_code is None:
- with patch("builtins.open", mock_open(read_data=image_contents)) as mock_file:
- response = Inference.detect_anomalies(
- lookoutvision_client, project_name, model_version, photo
- )
- mock_file.assert_called_with(photo, "rb")
- assert response["IsAnomalous"] == anomalous
- assert response["Confidence"] == confidence
- else:
- with pytest.raises(ClientError) as exc_info:
- with patch("builtins.open", mock_open(read_data=image_contents)):
- Inference.detect_anomalies(
- lookoutvision_client, project_name, model_version, photo
- )
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-def test_download_from_s3(make_stubber, monkeypatch):
- s3_resource = boto3.resource("s3")
- photo = "s3://amzn-s3-demo-bucket/test-photo.jpeg"
- file = "test-photo.jpeg"
-
- monkeypatch.setattr(
- s3_resource.meta.client,
- "download_file",
- lambda Filename, Bucket, Key, ExtraArgs, Callback, Config: None,
- )
-
- got_file = Inference.download_from_s3(s3_resource, photo)
- assert got_file == file
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_reject_on_classification(make_stubber, error_code):
- photo = "s3://amzn-s3-demo-bucket/test-photo.jpeg"
- prediction = {"IsAnomalous": True, "Confidence": 0.9}
-
- confidence_limit = 0.5
-
- if error_code is None:
- Inference.reject_on_classification(photo, prediction, confidence_limit)
- else:
- prediction = {"IsAnomalousX": True, "Confidence": 0.9}
- with pytest.raises(KeyError) as exc_info:
- Inference.reject_on_classification(photo, prediction, confidence_limit)
- assert exc_info.typename == "KeyError"
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_reject_on_anomaly_types(make_stubber, error_code):
- photo = "s3://amzn-s3-demo-bucket/test-photo.jpeg"
- prediction = {
- "IsAnomalous": True,
- "Confidence": 0.9,
- "Anomalies": [{"Name": "broken"}, {"Name": "cracked"}],
- }
-
- confidence_limit = 0.5
- anomaly_types_limit = 1
-
- if error_code is None:
- Inference.reject_on_anomaly_types(
- photo, prediction, confidence_limit, anomaly_types_limit
- )
- else:
- prediction = {
- "IsAnomalous": True,
- "Confidence": 0.9,
- "AnomaliesX": [{"Name": "broken"}, {"Name": "cracked"}],
- }
- with pytest.raises(KeyError) as exc_info:
- Inference.reject_on_anomaly_types(
- photo, prediction, confidence_limit, anomaly_types_limit
- )
- assert exc_info.typename == "KeyError"
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_reject_on_coverage(make_stubber, error_code):
- photo = "s3://amzn-s3-demo-bucket/test-photo.jpeg"
- prediction = {
- "IsAnomalous": True,
- "Confidence": 0.9,
- "Anomalies": [
- {"Name": "broken", "PixelAnomaly": {"TotalPercentageArea": 0.10}},
- {"Name": "broken", "PixelAnomaly": {"TotalPercentageArea": 0.50}},
- ],
- }
-
- confidence_limit = 0.5
- coverage_limit = 1
- anomaly_label = "broken"
-
- if error_code is None:
- Inference.reject_on_coverage(
- photo, prediction, confidence_limit, anomaly_label, coverage_limit
- )
- else:
- prediction = {
- "IsAnomalous": True,
- "Confidence": 0.9,
- "Anomalies": [
- {"Name": "broken", "PixelAnomalyX": {"TotalPercentageArea": 0.10}},
- {"Name": "broken", "PixelAnomalyX": {"TotalPercentageArea": 0.50}},
- ],
- }
- with pytest.raises(KeyError) as exc_info:
- Inference.reject_on_coverage(
- photo, prediction, confidence_limit, anomaly_label, coverage_limit
- )
- assert exc_info.typename == "KeyError"
diff --git a/python/example_code/lookoutvision/test/test_manifests/updates.manifest b/python/example_code/lookoutvision/test/test_manifests/updates.manifest
deleted file mode 100644
index 4ada5be8ac5..00000000000
--- a/python/example_code/lookoutvision/test/test_manifests/updates.manifest
+++ /dev/null
@@ -1 +0,0 @@
-{"source-ref":"s3://bucket/cookies/Anomaly/anomaly-1.jpg","auto-label":0,"auto-label-metadata":{"confidence":1,"job-name":"labeling-job/auto-label","class-name":"Anomaly","human-annotated":"yes","creation-date":"2022-04-28T00:35:57.102","type":"groundtruth/image-classification"}}
diff --git a/python/example_code/lookoutvision/test/test_models.py b/python/example_code/lookoutvision/test/test_models.py
deleted file mode 100644
index 6d43ca72015..00000000000
--- a/python/example_code/lookoutvision/test/test_models.py
+++ /dev/null
@@ -1,126 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Unit tests for models.py.
-"""
-
-import datetime
-import boto3
-from botocore.exceptions import ClientError
-import pytest
-
-from models import Models
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_create_model(make_stubber, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- model_version = "test-model"
- model_arn = "test-arn"
- out_buck = "amzn-s3-demo-bucket"
- out_folder = "test-results"
- training_results = f"s3://{out_buck}/{out_folder}"
- status = "TRAINED"
-
- lookoutvision_stubber.stub_create_model(
- project_name, out_buck, out_folder, model_arn, model_version
- )
- lookoutvision_stubber.stub_describe_model(
- project_name, model_version, model_arn, status, error_code=error_code
- )
-
- if error_code is None:
- got_status, got_version = Models.create_model(
- lookoutvision_client, project_name, training_results
- )
- assert got_status == status
- assert got_version == model_version
- else:
- with pytest.raises(ClientError) as exc_info:
- Models.create_model(lookoutvision_client, project_name, training_results)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_describe_model(make_stubber, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- model_version = "test-model"
- model_arn = "test-arn"
- description = "test description"
- status = "TRAINED"
- message = "Test message!"
- created = datetime.datetime.now()
- trained = created + datetime.timedelta(minutes=10)
- recall = 0.3
- precision = 0.5
- f1 = 0.7
- out_buck = "amzn-s3-demo-bucket"
- out_folder = "test-folder"
-
- lookoutvision_stubber.stub_describe_model(
- project_name,
- model_version,
- model_arn,
- status,
- {
- "description": description,
- "message": message,
- "created": created,
- "trained": trained,
- "recall": recall,
- "precision": precision,
- "f1": f1,
- "out_bucket": out_buck,
- "out_folder": out_folder,
- },
- error_code=error_code,
- )
-
- if error_code is None:
- Models.describe_model(lookoutvision_client, project_name, model_version)
- else:
- with pytest.raises(ClientError) as exc_info:
- Models.describe_model(lookoutvision_client, project_name, model_version)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_describe_models(make_stubber, monkeypatch, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- model = "test-model"
-
- lookoutvision_stubber.stub_list_models(project_name, [model], error_code=error_code)
-
- monkeypatch.setattr(Models, "describe_model", lambda x, y, z: None)
-
- if error_code is None:
- Models.describe_models(lookoutvision_client, project_name)
- else:
- with pytest.raises(ClientError) as exc_info:
- Models.describe_models(lookoutvision_client, project_name)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_delete_model(make_stubber, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- model_version = "test-model"
-
- lookoutvision_stubber.stub_delete_model(project_name, model_version)
- lookoutvision_stubber.stub_list_models(project_name, [], error_code=error_code)
-
- if error_code is None:
- Models.delete_model(lookoutvision_client, project_name, model_version)
- else:
- with pytest.raises(ClientError) as exc_info:
- Models.delete_model(lookoutvision_client, project_name, model_version)
- assert exc_info.value.response["Error"]["Code"] == error_code
diff --git a/python/example_code/lookoutvision/test/test_projects.py b/python/example_code/lookoutvision/test/test_projects.py
deleted file mode 100644
index cc1c10843c5..00000000000
--- a/python/example_code/lookoutvision/test/test_projects.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Unit tests for projects.py.
-"""
-
-import datetime
-import boto3
-from botocore.exceptions import ClientError
-import pytest
-
-from models import Models
-from projects import Projects
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_create_project(make_stubber, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- project_arn = "test-arn"
-
- lookoutvision_stubber.stub_create_project(
- project_name, project_arn, error_code=error_code
- )
-
- if error_code is None:
- got_project_arn = Projects.create_project(lookoutvision_client, project_name)
- assert got_project_arn == project_arn
- else:
- with pytest.raises(ClientError) as exc_info:
- Projects.create_project(lookoutvision_client, project_name)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize("error_code", [None, "TestException"])
-def test_delete_project(make_stubber, error_code):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project_name"
- project_arn = "test-arn"
-
- lookoutvision_stubber.stub_delete_project(
- project_name, project_arn, error_code=error_code
- )
-
- if error_code is None:
- Projects.delete_project(lookoutvision_client, project_name)
- else:
- with pytest.raises(ClientError) as exc_info:
- Projects.delete_project(lookoutvision_client, project_name)
- assert exc_info.value.response["Error"]["Code"] == error_code
-
-
-@pytest.mark.parametrize(
- "error_code,stop_on_method",
- [
- (None, None),
- ("TestException", "stub_list_projects"),
- ("TestException", "stub_describe_project"),
- ("TestException", "stub_list_models"),
- ],
-)
-def test_list_projects(
- make_stubber, stub_runner, monkeypatch, error_code, stop_on_method
-):
- lookoutvision_client = boto3.client("lookoutvision")
- lookoutvision_stubber = make_stubber(lookoutvision_client)
- project_name = "test-project"
- project_arn = "test-arn"
- created = datetime.datetime.now()
- model_version = "test-model"
- dataset = {"DatasetType": "testing", "StatusMessage": "nicely tested"}
-
- monkeypatch.setattr(Models, "describe_model", lambda x, y, z: None)
-
- with stub_runner(error_code, stop_on_method) as runner:
- runner.add(
- lookoutvision_stubber.stub_list_projects,
- [project_name],
- [{"arn": project_arn, "created": created}],
- )
- runner.add(lookoutvision_stubber.stub_describe_project, project_name, [dataset])
- runner.add(
- lookoutvision_stubber.stub_list_models, project_name, [model_version]
- )
-
- if error_code is None:
- Projects.list_projects(lookoutvision_client)
- else:
- with pytest.raises(ClientError) as exc_info:
- Projects.list_projects(lookoutvision_client)
- assert exc_info.value.response["Error"]["Code"] == error_code
diff --git a/python/example_code/lookoutvision/train.manifest b/python/example_code/lookoutvision/train.manifest
deleted file mode 100644
index 0d71c6f1307..00000000000
--- a/python/example_code/lookoutvision/train.manifest
+++ /dev/null
@@ -1 +0,0 @@
-{"source-ref": "s3://dest-bucket/stubber_test/train/images/cookies/Anomaly/anomaly-1.jpg", "auto-label": 0, "auto-label-metadata": {"confidence": 1, "job-name": "labeling-job/auto-label", "class-name": "Anomaly", "human-annotated": "yes", "creation-date": "2022-04-28T00:35:57.102", "type": "groundtruth/image-classification"}}
diff --git a/python/example_code/lookoutvision/train_host.py b/python/example_code/lookoutvision/train_host.py
deleted file mode 100644
index f1bba264665..00000000000
--- a/python/example_code/lookoutvision/train_host.py
+++ /dev/null
@@ -1,170 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Purpose
-
-Shows how to create and optionally start an Amazon Lookout for Vision model.
-"""
-
-import argparse
-import logging
-import boto3
-from projects import Projects
-from datasets import Datasets
-from models import Models
-from hosting import Hosting
-
-logger = logging.getLogger(__name__)
-
-
-def start_model(lookoutvision_client, project_name, version):
- """
- Starts a model, if requested.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param project_name: The name of the project that contains the model version
- you want to start.
- :param: version: The version of the model that you want to start.
- """
- start = input("Do you want to start your model (y/n)?")
- if start == "y":
- print("Starting model...")
- Hosting.start_model(lookoutvision_client, project_name, version, 1)
- print("Your model is ready to use with the following command.\n")
- print(f"python inference.py {project_name} {version} ")
- print(
- "\nStop your model when you're done. You're charged while it's running. "
- "See hosting.py"
- )
- else:
- print("Not starting model.")
-
-
-def create_dataset(
- lookoutvision_client,
- s3_resource,
- bucket,
- project_name,
- dataset_images,
- dataset_type,
-):
- """
- Creates a manifest from images in the supplied bucket and then creates
- a dataset.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param s3_resource: A Boto3 Amazon S3 client.
- :param bucket: The bucket that stores the manifest file.
- :param project_name: The project in which to create the dataset.
- :param dataset_images: The location of the images referenced by the dataset.
- :param dataset_type: The type of dataset to create (train or test).
- """
- print(f"Creating {dataset_type} dataset...")
-
- manifest_file = f"s3://{bucket}/{project_name}/manifests/{dataset_type}.manifest"
-
- logger.info("Creating %s manifest file in %s.", dataset_type, manifest_file)
- Datasets.create_manifest_file_s3(s3_resource, dataset_images, manifest_file)
-
- logger.info("Create %s dataset for project %s", dataset_type, project_name)
- Datasets.create_dataset(
- lookoutvision_client, project_name, manifest_file, dataset_type
- )
-
-
-def train_model(lookoutvision_client, bucket, project_name):
- """
- Trains a model.
-
- :param lookoutvision_client: A Boto3 Lookout for Vision client.
- :param bucket: The bucket where the training output is stored.
- :param project_name: The project that you want to train.
- """
- print("Training model...")
- training_results = f"{bucket}/{project_name}/output/"
- status, version = Models.create_model(
- lookoutvision_client, project_name, training_results
- )
-
- Models.describe_model(lookoutvision_client, project_name, version)
- if status == "TRAINED":
- print(
- "\nCheck the performance metrics and decide if you need to improve "
- "the model performance."
- )
- print(
- "\nMore information: "
- "https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/improve.html"
- )
- print("If you are satisfied with your model, you can start it.")
- start_model(lookoutvision_client, project_name, version)
- else:
- print("Model training failed.")
-
-
-def main():
- """
- Creates and optionally starts an Amazon Lookout for Vision model using
- command line arguments.
-
- A new project, training dataset, optional test dataset, and model are created.
- After model training is completed, you can use the code in inference.py to try your
- model with an image.
- For the training and test folders, place normal images in a folder named normal and
- anomalous images in a folder named anomaly.
- Make sure that bucket and the training/test Amazon S3 paths are in the same AWS Region.
- """
- logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
- parser = argparse.ArgumentParser(usage=argparse.SUPPRESS)
- parser.add_argument("project", help="A unique name for your project")
- parser.add_argument(
- "bucket",
- help="The bucket used to upload your manifest files and store training output",
- )
- parser.add_argument(
- "training",
- help="The Amazon S3 path where the service gets the training images. ",
- )
- parser.add_argument(
- "test",
- nargs="?",
- default=None,
- help="(Optional) The Amazon S3 path where the service gets the test images.",
- )
- args = parser.parse_args()
-
- project_name = args.project
- bucket = args.bucket
- training_images = args.training
- test_images = args.test
-
- session = boto3.Session(profile_name="lookoutvision-access")
-
- lookoutvision_client = session.client("lookoutvision")
-
- s3_resource = session.resource("s3")
-
- print(f"Storing information in s3://{bucket}/{project_name}/")
- print("Creating project...")
- Projects.create_project(lookoutvision_client, project_name)
-
- create_dataset(
- lookoutvision_client,
- s3_resource,
- bucket,
- project_name,
- training_images,
- "train",
- )
- if test_images is not None:
- create_dataset(
- lookoutvision_client, s3_resource, bucket, project_name, test_images, "test"
- )
-
- # Train the model and optionally start hosting.
- train_model(lookoutvision_client, bucket, project_name)
-
-
-if __name__ == "__main__":
- main()
diff --git a/python/example_code/lookoutvision/update_dataset.py b/python/example_code/lookoutvision/update_dataset.py
deleted file mode 100644
index 9dedba03ae9..00000000000
--- a/python/example_code/lookoutvision/update_dataset.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-"""
-Purpose
-
-Amazon Lookout for Vision dataset code examples used in the service documentation:
-https://docs.aws.amazon.com/lookout-for-vision/latest/developer-guide/edit-dataset.html
-Shows how to update a Lookout for Vision dataset with a manifest file.
-"""
-import logging
-import argparse
-import boto3
-from botocore.exceptions import ClientError
-from datasets import Datasets
-
-
-logger = logging.getLogger(__name__)
-
-
-def add_arguments(parser):
- """
- Adds command line arguments to the parser.
- :param parser: The command line parser.
- """
-
- parser.add_argument(
- "project_name",
- help="The Amazon Resource Name (ARN) of the dataset that you want to update.",
- )
-
- parser.add_argument(
- "dataset_type",
- help="The type of the dataset that you want to update (train or test).",
- )
-
- parser.add_argument(
- "updates_file",
- help="The manifest file of JSON lines that contains the updates.",
- )
-
-
-def main():
- logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
-
- try:
- # Get command line arguments.
- parser = argparse.ArgumentParser(usage=argparse.SUPPRESS)
- add_arguments(parser)
- args = parser.parse_args()
-
- print(
- f"Updating {args.dataset_type} dataset for project {args.project_name} "
- "with entries from {args.updates_file}."
- )
-
- # Update the dataset.
- session = boto3.Session(profile_name="lookoutvision-access")
-
- lookoutvision_client = session.client("lookoutvision")
-
- status, status_message = Datasets.update_dataset_entries(
- lookoutvision_client,
- args.project_name,
- args.dataset_type,
- args.updates_file,
- )
-
- print(f"Finished updates dataset: {status} : {status_message}")
-
- except ClientError as err:
- logger.exception("Problem updating dataset: %s", err)
- print(f"Problem updating dataset: {err}")
- except Exception as err:
- logger.exception("Problem updating dataset: %s", err)
- print(f"Problem updating dataset: {err}")
-
-
-if __name__ == "__main__":
- main()