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()