kuva-reader 1.1.1__tar.gz → 1.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kuva-reader might be problematic. Click here for more details.
- kuva_reader-1.1.2/.gitignore +134 -0
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/PKG-INFO +11 -18
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/kuva_reader/__init__.py +1 -1
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/kuva_reader/reader/level0.py +15 -6
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/kuva_reader/reader/level1.py +22 -7
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/kuva_reader/reader/product_base.py +1 -1
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/pyproject.toml +32 -24
- kuva_reader-1.1.2/tests/__init__.py +0 -0
- kuva_reader-1.1.2/tests/test_reader.py +74 -0
- kuva_reader-1.1.2/uv.lock +919 -0
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/README.md +0 -0
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/kuva_reader/py.typed +0 -0
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/kuva_reader/reader/__init__.py +0 -0
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/kuva_reader/reader/image.py +0 -0
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/kuva_reader/reader/level2.py +0 -0
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/kuva_reader/reader/py.typed +0 -0
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/kuva_reader/reader/read.py +0 -0
- {kuva_reader-1.1.1 → kuva_reader-1.1.2}/kuva_reader/reader/utils.py +0 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
*.ipynb
|
|
12
|
+
build/
|
|
13
|
+
develop-eggs/
|
|
14
|
+
dist/
|
|
15
|
+
downloads/
|
|
16
|
+
eggs/
|
|
17
|
+
.eggs/
|
|
18
|
+
lib/
|
|
19
|
+
lib64/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.coverage
|
|
43
|
+
.coverage.*
|
|
44
|
+
.cache
|
|
45
|
+
nosetests.xml
|
|
46
|
+
coverage.xml
|
|
47
|
+
*.cover
|
|
48
|
+
.hypothesis/
|
|
49
|
+
.pytest_cache/
|
|
50
|
+
|
|
51
|
+
# Translations
|
|
52
|
+
*.mo
|
|
53
|
+
*.pot
|
|
54
|
+
|
|
55
|
+
# Django stuff:
|
|
56
|
+
*.log
|
|
57
|
+
local_settings.py
|
|
58
|
+
db.sqlite3
|
|
59
|
+
|
|
60
|
+
# Flask stuff:
|
|
61
|
+
instance/
|
|
62
|
+
.webassets-cache
|
|
63
|
+
|
|
64
|
+
# Torch stuff
|
|
65
|
+
lightning_logs/
|
|
66
|
+
|
|
67
|
+
# Scrapy stuff:
|
|
68
|
+
.scrapy
|
|
69
|
+
|
|
70
|
+
# Sphinx documentation
|
|
71
|
+
docs/_build/
|
|
72
|
+
|
|
73
|
+
# PyBuilder
|
|
74
|
+
target/
|
|
75
|
+
|
|
76
|
+
# Jupyter Notebook
|
|
77
|
+
.ipynb_checkpoints
|
|
78
|
+
|
|
79
|
+
# VSCode
|
|
80
|
+
.vscode
|
|
81
|
+
|
|
82
|
+
# pyenv
|
|
83
|
+
.python-version
|
|
84
|
+
|
|
85
|
+
# celery beat schedule file
|
|
86
|
+
celerybeat-schedule
|
|
87
|
+
|
|
88
|
+
# SageMath parsed files
|
|
89
|
+
*.sage.py
|
|
90
|
+
|
|
91
|
+
# Environments
|
|
92
|
+
.env
|
|
93
|
+
.venv
|
|
94
|
+
env/
|
|
95
|
+
venv/
|
|
96
|
+
ENV/
|
|
97
|
+
env.bak/
|
|
98
|
+
venv.bak/
|
|
99
|
+
|
|
100
|
+
# Spyder project settings
|
|
101
|
+
.spyderproject
|
|
102
|
+
.spyproject
|
|
103
|
+
|
|
104
|
+
# Rope project settings
|
|
105
|
+
.ropeproject
|
|
106
|
+
|
|
107
|
+
# mkdocs documentation
|
|
108
|
+
/site
|
|
109
|
+
|
|
110
|
+
# mypy
|
|
111
|
+
.mypy_cache/
|
|
112
|
+
|
|
113
|
+
# Direnv stuff
|
|
114
|
+
.direnv/
|
|
115
|
+
.envrc
|
|
116
|
+
|
|
117
|
+
# Poetry
|
|
118
|
+
# poetry.lock
|
|
119
|
+
|
|
120
|
+
# Supervisord
|
|
121
|
+
supervisord.log
|
|
122
|
+
supervisord.pid
|
|
123
|
+
|
|
124
|
+
# Debug folders
|
|
125
|
+
_debug/
|
|
126
|
+
|
|
127
|
+
# Kuva data
|
|
128
|
+
*.tif
|
|
129
|
+
*.tiff
|
|
130
|
+
*.npy
|
|
131
|
+
hyperfield*.json
|
|
132
|
+
|
|
133
|
+
# Do not ignore Kuva files in the test_data directory
|
|
134
|
+
!kuva-reader/tests/test_data/**
|
|
@@ -1,22 +1,16 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: kuva-reader
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.2
|
|
4
4
|
Summary: Manipulate the Kuva Space image and metadata formats
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Requires-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
Requires-Dist: kuva-geometry (>=1.0.1,<2.0.0)
|
|
15
|
-
Requires-Dist: kuva-metadata (>=1.1.1,<2.0.0)
|
|
16
|
-
Requires-Dist: numpy (>=1.26.4,<2.0.0)
|
|
17
|
-
Requires-Dist: numpy-quaternion (>=2022.4.4,<2023.0.0)
|
|
18
|
-
Requires-Dist: pint (>=0.22,<0.23)
|
|
19
|
-
Requires-Dist: rasterio (>=1.4.1,<2.0.0)
|
|
5
|
+
Author-email: Guillem Ballesteros <guillem@kuvaspace.com>, Lennert Antson <lennert.antson@kuvaspace.com>, Arthur Vandenhoeke <arthur.vandenhoeke@kuvaspace.com>, Olli Eloranta <olli.eloranta@kuvaspace.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Requires-Python: <=3.13,>=3.10
|
|
8
|
+
Requires-Dist: kuva-geometry<2.0.0,>=1.0.1
|
|
9
|
+
Requires-Dist: kuva-metadata<2.0.0,>=1.1.1
|
|
10
|
+
Requires-Dist: numpy-quaternion>=2023.4.4
|
|
11
|
+
Requires-Dist: numpy>=1.26.4
|
|
12
|
+
Requires-Dist: pint<1.0.0,>=0.22
|
|
13
|
+
Requires-Dist: rasterio<2,>=1.4.3
|
|
20
14
|
Description-Content-Type: text/markdown
|
|
21
15
|
|
|
22
16
|
<div align="center">
|
|
@@ -128,4 +122,3 @@ The `kuva-reader` project software is under the [MIT license](https://github.com
|
|
|
128
122
|
# Status of unit tests
|
|
129
123
|
|
|
130
124
|
[](https://github.com/KuvaSpace/kuva-data-processing/actions/workflows/test-kuva-reader.yml)
|
|
131
|
-
|
|
@@ -61,7 +61,7 @@ class Level0Product(ProductBase[MetadataLevel0]):
|
|
|
61
61
|
) -> None:
|
|
62
62
|
super().__init__(image_path, metadata, target_ureg)
|
|
63
63
|
|
|
64
|
-
self.
|
|
64
|
+
self._images = {
|
|
65
65
|
camera: cast(
|
|
66
66
|
rio.DatasetReader,
|
|
67
67
|
rio.open(
|
|
@@ -97,6 +97,12 @@ class Level0Product(ProductBase[MetadataLevel0]):
|
|
|
97
97
|
"""Return the datarray for the chosen camera."""
|
|
98
98
|
return self.images[camera]
|
|
99
99
|
|
|
100
|
+
@property
|
|
101
|
+
def images(self) -> dict[str, rio.DatasetReader]:
|
|
102
|
+
if self._images is None:
|
|
103
|
+
raise RuntimeError("Images has been released.")
|
|
104
|
+
return self._images
|
|
105
|
+
|
|
100
106
|
def keys(self) -> list[str]:
|
|
101
107
|
"""Easy access to the camera keys."""
|
|
102
108
|
return list(self.images.keys())
|
|
@@ -230,11 +236,14 @@ class Level0Product(ProductBase[MetadataLevel0]):
|
|
|
230
236
|
"""Explicitely closes the Rasterio DatasetReaders and releases the memory of
|
|
231
237
|
the `images` variable.
|
|
232
238
|
"""
|
|
233
|
-
|
|
234
|
-
self.
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
239
|
+
if self._images is not None:
|
|
240
|
+
for k in self._images.keys():
|
|
241
|
+
self._images[k].close()
|
|
242
|
+
|
|
243
|
+
del self._images
|
|
244
|
+
# We know that images are not None as long as somebody doesn't call
|
|
245
|
+
# this function beforehand....
|
|
246
|
+
self._images = None
|
|
238
247
|
|
|
239
248
|
|
|
240
249
|
def generate_level_0_metafile():
|
|
@@ -50,7 +50,7 @@ class Level1ABProduct(ProductBase[MetadataLevel1AB]):
|
|
|
50
50
|
) -> None:
|
|
51
51
|
super().__init__(image_path, metadata, target_ureg)
|
|
52
52
|
|
|
53
|
-
self.
|
|
53
|
+
self._image = cast(
|
|
54
54
|
rio.DatasetReader,
|
|
55
55
|
rio.open(self.image_path / "L1B.tif"),
|
|
56
56
|
)
|
|
@@ -73,6 +73,12 @@ class Level1ABProduct(ProductBase[MetadataLevel1AB]):
|
|
|
73
73
|
else:
|
|
74
74
|
return f"{self.__class__.__name__} loaded from '{self.image_path}'"
|
|
75
75
|
|
|
76
|
+
@property
|
|
77
|
+
def image(self) -> rio.DatasetReader:
|
|
78
|
+
if self._image is None:
|
|
79
|
+
raise RuntimeError("Images has been released.")
|
|
80
|
+
return self._image
|
|
81
|
+
|
|
76
82
|
def footprint(self, crs="") -> Polygon:
|
|
77
83
|
"""The product footprint as a Shapely polygon."""
|
|
78
84
|
return image_footprint(self.image, crs)
|
|
@@ -130,8 +136,10 @@ class Level1ABProduct(ProductBase[MetadataLevel1AB]):
|
|
|
130
136
|
"""Explicitely closes the Rasterio DatasetReader and releases the memory of
|
|
131
137
|
the `image` variable.
|
|
132
138
|
"""
|
|
133
|
-
|
|
134
|
-
|
|
139
|
+
if self._image is not None:
|
|
140
|
+
self._image.close()
|
|
141
|
+
del self._image
|
|
142
|
+
self._image = None
|
|
135
143
|
|
|
136
144
|
|
|
137
145
|
class Level1CProduct(ProductBase[MetadataLevel1C]):
|
|
@@ -170,7 +178,7 @@ class Level1CProduct(ProductBase[MetadataLevel1C]):
|
|
|
170
178
|
) -> None:
|
|
171
179
|
super().__init__(image_path, metadata, target_ureg)
|
|
172
180
|
|
|
173
|
-
self.
|
|
181
|
+
self._image = cast(
|
|
174
182
|
rio.DatasetReader,
|
|
175
183
|
rio.open(self.image_path / "L1C.tif"),
|
|
176
184
|
)
|
|
@@ -193,6 +201,12 @@ class Level1CProduct(ProductBase[MetadataLevel1C]):
|
|
|
193
201
|
else:
|
|
194
202
|
return f"{self.__class__.__name__} loaded from '{self.image_path}'"
|
|
195
203
|
|
|
204
|
+
@property
|
|
205
|
+
def image(self) -> rio.DatasetReader:
|
|
206
|
+
if self._image is None:
|
|
207
|
+
raise RuntimeError("Images has been released.")
|
|
208
|
+
return self._image
|
|
209
|
+
|
|
196
210
|
def footprint(self, crs="") -> Polygon:
|
|
197
211
|
"""The product footprint as a Shapely polygon."""
|
|
198
212
|
return image_footprint(self.image, crs)
|
|
@@ -231,9 +245,10 @@ class Level1CProduct(ProductBase[MetadataLevel1C]):
|
|
|
231
245
|
"""Explicitely closes the Rasterio DatasetReader and releases the memory of
|
|
232
246
|
the `image` variable.
|
|
233
247
|
"""
|
|
234
|
-
self.
|
|
235
|
-
|
|
236
|
-
|
|
248
|
+
if self._image is not None:
|
|
249
|
+
self._image.close()
|
|
250
|
+
del self._image
|
|
251
|
+
self._image = None
|
|
237
252
|
|
|
238
253
|
|
|
239
254
|
def generate_level_1_metafile():
|
|
@@ -35,7 +35,7 @@ class ProductBase(Generic[TMetadata], metaclass=ABCMeta):
|
|
|
35
35
|
def __init__(
|
|
36
36
|
self,
|
|
37
37
|
image_path: Path,
|
|
38
|
-
metadata:
|
|
38
|
+
metadata: TMetadata | None = None,
|
|
39
39
|
target_ureg: UnitRegistry | None = None,
|
|
40
40
|
):
|
|
41
41
|
self.image_path = Path(image_path)
|
|
@@ -1,35 +1,43 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = [
|
|
3
|
-
build-backend = "
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
4
|
|
|
5
|
-
[
|
|
5
|
+
[project]
|
|
6
6
|
name = "kuva-reader"
|
|
7
|
-
version = "1.1.
|
|
7
|
+
version = "1.1.2"
|
|
8
8
|
description = "Manipulate the Kuva Space image and metadata formats"
|
|
9
|
-
authors = [
|
|
9
|
+
authors = [
|
|
10
|
+
{ name = "Guillem Ballesteros", email = "guillem@kuvaspace.com" },
|
|
11
|
+
{ name = "Lennert Antson", email = "lennert.antson@kuvaspace.com" },
|
|
12
|
+
{ name = "Arthur Vandenhoeke", email = "arthur.vandenhoeke@kuvaspace.com" },
|
|
13
|
+
{ name = "Olli Eloranta", email = "olli.eloranta@kuvaspace.com" },
|
|
14
|
+
]
|
|
10
15
|
readme = "README.md"
|
|
11
16
|
license = "MIT"
|
|
17
|
+
requires-python = ">=3.10, <=3.13"
|
|
18
|
+
dependencies = [
|
|
19
|
+
"numpy>=1.26.4",
|
|
20
|
+
"numpy-quaternion>=2023.4.4",
|
|
21
|
+
"pint >=0.22, <1.0.0",
|
|
22
|
+
"rasterio>=1.4.3,<2",
|
|
23
|
+
"kuva-geometry>=1.0.1,<2.0.0",
|
|
24
|
+
"kuva-metadata>=1.1.1,<2.0.0"
|
|
25
|
+
]
|
|
26
|
+
scripts.make-l0-meta = "kuva_reader.reader.level0:generate_level_0_metafile"
|
|
27
|
+
scripts.make-l1-meta = "kuva_reader.reader.level1:generate_level_1_metafile"
|
|
28
|
+
|
|
29
|
+
[dependency-groups]
|
|
30
|
+
dev = [
|
|
31
|
+
"pyright>=1.1.403",
|
|
32
|
+
"pytest>=7.4.2,<8",
|
|
33
|
+
"ruff>=0.12.4",
|
|
34
|
+
]
|
|
12
35
|
|
|
13
36
|
[tool.ruff]
|
|
14
37
|
target-version = "py310"
|
|
15
38
|
line-length = 88
|
|
16
39
|
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
|
17
40
|
|
|
18
|
-
[tool.mypy]
|
|
19
|
-
ignore_missing_imports = true
|
|
20
|
-
|
|
21
|
-
[tool.poetry.scripts]
|
|
22
|
-
make-l0-meta = "kuva_reader.reader.level0:generate_level_0_metafile"
|
|
23
|
-
make-l1-meta = "kuva_reader.reader.level1:generate_level_1_metafile"
|
|
24
|
-
|
|
25
|
-
[tool.poetry.dependencies]
|
|
26
|
-
python = ">=3.10,<=3.13"
|
|
27
|
-
numpy = "^1.26.4"
|
|
28
|
-
numpy-quaternion = "^2022.4.4"
|
|
29
|
-
pint = "^0.22"
|
|
30
|
-
rasterio = "^1.4.1"
|
|
31
|
-
kuva-geometry = "^1.0.1"
|
|
32
|
-
kuva-metadata = "^1.1.1"
|
|
33
41
|
|
|
34
42
|
[tool.ruff.lint]
|
|
35
43
|
select = [ "E", "F", "A", "DTZ", "NPY", "I", "ISC", "B003", "B004", "B015", "PTH", "D100", "D101", "D102", "D103", "D104", "D105", "D200", "W191", "W291", "W293", "N801", "N804", "N805", "T100", "S105", "S106", "S108", "S604", "S602", "S609", "UP003", "UP005", "UP006", "UP007", "UP008", "UP032", "UP035", "RUF001", "RUF200", "RUF013", "C901", "COM818", "RSE102", "EM101",]
|
|
@@ -44,7 +52,7 @@ convention = "numpy"
|
|
|
44
52
|
[tool.ruff.lint.per-file-ignores]
|
|
45
53
|
"__init__.py" = [ "F401", "D104", "E402",]
|
|
46
54
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
# Uncomment during development
|
|
56
|
+
# [tool.uv.sources]
|
|
57
|
+
# kuva-geometry = { path = "../kuva-geometry" }
|
|
58
|
+
# kuva-metadata = { path = "../kuva-metadata" }
|
|
File without changes
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Tests for reading of actual Hyperfield products.
|
|
2
|
+
|
|
3
|
+
NOTE: To limit data size, the test data used in the kuva-reader tests have been cropped,
|
|
4
|
+
and most of the bands have been removed. The original images are from a normal
|
|
5
|
+
acquisition."""
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
from kuva_reader import Level1CProduct, Level2AProduct, read_product
|
|
12
|
+
|
|
13
|
+
TEST_DATA_ROOT = Path(__file__).parent / "test_data"
|
|
14
|
+
L1C_PATH = TEST_DATA_ROOT / "hyperfield1a_L1C_20250310T142413"
|
|
15
|
+
L2A_PATH = TEST_DATA_ROOT / "hyperfield1a_L2A_20250310T142413"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.fixture
|
|
19
|
+
def l1c_product() -> Level1CProduct:
|
|
20
|
+
"""Fetch test L1C product.
|
|
21
|
+
|
|
22
|
+
NOTE: This is a cropped version of a Hyperfield-1A L1C cube with few bands (5)
|
|
23
|
+
"""
|
|
24
|
+
return Level1CProduct(L1C_PATH)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.fixture
|
|
28
|
+
def l2a_product() -> Level2AProduct:
|
|
29
|
+
"""Fetch test L2A product.
|
|
30
|
+
|
|
31
|
+
NOTE: This is a cropped version of a Hyperfield-1A L2A cube with few bands (5)
|
|
32
|
+
"""
|
|
33
|
+
return Level2AProduct(L2A_PATH)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_product_reader():
|
|
37
|
+
"""Read the correct products with product reader function"""
|
|
38
|
+
with pytest.raises(ValueError):
|
|
39
|
+
read_product(L2A_PATH.parent)
|
|
40
|
+
|
|
41
|
+
product = read_product(L2A_PATH)
|
|
42
|
+
assert product.__class__ == Level2AProduct
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_read_l1c(l1c_product: Level1CProduct):
|
|
46
|
+
"""Product reading was successful based on image, metadata and tags"""
|
|
47
|
+
# Check that image was loaded with correct number of bands
|
|
48
|
+
assert l1c_product.image.read().shape[0] == 5
|
|
49
|
+
# Check that metadata exists and has same shape as image
|
|
50
|
+
assert len(l1c_product.metadata.image.bands) == 5
|
|
51
|
+
# Check that tags exist
|
|
52
|
+
assert l1c_product.data_tags.get("AREA_OR_POINT") is not None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_read_l2a(l2a_product: Level2AProduct):
|
|
56
|
+
"""Product reading was successful based on image, metadata and tags"""
|
|
57
|
+
# Check that image was loaded with correct number of bands
|
|
58
|
+
assert l2a_product.image.read().shape[0] == 5
|
|
59
|
+
# Check that metadata exists and has same shape as image
|
|
60
|
+
assert len(l2a_product.metadata.image.bands) == 5
|
|
61
|
+
# Check that tags exist
|
|
62
|
+
assert l2a_product.data_tags.get("AREA_OR_POINT") is not None
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_read_bad_pixel_mask_l1c(l1c_product: Level1CProduct):
|
|
66
|
+
"""Bad pixel mask is correctly loaded and is same shape as product"""
|
|
67
|
+
bad_pixel_mask = l1c_product.get_bad_pixel_mask().read()
|
|
68
|
+
assert bad_pixel_mask.shape[1:] == l1c_product.image.shape
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_read_bad_pixel_mask_l2a(l2a_product: Level2AProduct):
|
|
72
|
+
"""Bad pixel mask is correctly loaded and is same shape as product"""
|
|
73
|
+
bad_pixel_mask = l2a_product.get_bad_pixel_mask().read()
|
|
74
|
+
assert bad_pixel_mask.shape[1:] == l2a_product.image.shape
|