Coverage for src/io_collection/save/save_image.py: 100%
36 statements
« prev ^ index » next coverage.py v7.5.1, created at 2024-09-25 19:09 +0000
« prev ^ index » next coverage.py v7.5.1, created at 2024-09-25 19:09 +0000
1import io
2import tempfile
3from pathlib import Path
5import boto3
6import numpy as np
7from bioio.writers import OmeTiffWriter
8from PIL import Image
10from io_collection.save.save_buffer import _save_buffer_to_s3
12EXTENSIONS = (".ome.tif", ".ome.tiff", ".png")
15def save_image(location: str, key: str, image: np.ndarray) -> None:
16 """
17 Save image array to key at specified location.
19 Method will save to the S3 bucket if the location begins with the **s3://**
20 protocol, otherwise it assumes the location is a local path.
22 Parameters
23 ----------
24 location
25 Object location (local path or S3 bucket).
26 key
27 Object key ending in `.ome.tiff` or `.png`.
28 image
29 Image array.
30 """
32 if not key.endswith(EXTENSIONS):
33 extensions = " | ".join([ext[1:] for ext in EXTENSIONS])
34 message = f"key [ {key} ] must have [ {extensions} ] extension"
35 raise ValueError(message)
37 if location[:5] == "s3://":
38 _save_image_to_s3(location[5:], key, image)
39 else:
40 _save_image_to_fs(location, key, image)
43def _save_image_to_fs(path: str, key: str, image: np.ndarray) -> None:
44 """
45 Save image array to key on local file system.
47 Parameters
48 ----------
49 path
50 Local object path.
51 key
52 Object key ending in `.ome.tiff` or `.png`.
53 image
54 Image array.
55 """
57 full_path = Path(path) / key
58 full_path.parent.mkdir(parents=True, exist_ok=True)
60 if key.endswith((".ome.tiff", ".ome.tif")):
61 OmeTiffWriter.save(image, full_path)
62 elif key.endswith(".png"):
63 Image.fromarray(image).save(full_path) # type: ignore[no-untyped-call]
66def _save_image_to_s3(bucket: str, key: str, image: np.ndarray) -> None:
67 """
68 Save image array to key in AWS S3 bucket.
70 Parameters
71 ----------
72 bucket
73 AWS S3 bucket name.
74 key
75 Object key ending in `.ome.tiff` or `.png`.
76 image
77 Image array.
78 """
80 s3_client = boto3.client("s3")
82 if key.endswith((".ome.tiff", ".ome.tif")):
83 with tempfile.TemporaryDirectory() as temp_dir:
84 temp_path = Path(temp_dir) / "temp.ome.tiff"
85 OmeTiffWriter.save(image, temp_path)
87 with temp_path.open("rb") as fileobj:
88 s3_client.upload_fileobj(fileobj, bucket, key)
89 elif key.endswith(".png"):
90 with io.BytesIO() as buffer:
91 Image.fromarray(image).save(buffer, format="png") # type: ignore[no-untyped-call]
92 _save_buffer_to_s3(bucket, key, buffer, "image/png")