kuva-reader 0.1.3__py3-none-any.whl → 0.1.4__py3-none-any.whl

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/__init__.py CHANGED
@@ -4,20 +4,20 @@ Observation (EO) products. The module handles the reading and parsing of image
4
4
  data, as well as extracting and structuring the associated metadata to
5
5
  facilitate further analysis or visualization.
6
6
 
7
- ## Key Features
7
+ Key Features
8
8
 
9
- - **Open EO Products**: Load satellite images and corresponding metadata from
10
- various data formats.
11
- - **Access Metadata**: Retrieve information such as acquisition time, satellite
9
+ - Open EO Products: Load satellite images and corresponding metadata from
10
+ various dataformats.
11
+ - Access Metadata: Retrieve information such as acquisition time, satellite
12
12
  name, sensor type, geospatial coordinates, and any custom metadata embedded
13
13
  within the product.
14
- - **Image Handling**: Manage the loading of image data for efficient use in
14
+ - Image Handling: Manage the loading of image data for efficient use in
15
15
  analytical processes.
16
16
 
17
- ## Dependencies
18
- - **kuva-metadata**: A specialized library that handles the extraction and
17
+ Dependencies
18
+ - kuva-metadata: A specialized library that handles the extraction and
19
19
  parsing of metadata associated with Kuva Space products.
20
- - **xarray**: Used for loading image data as arrays with extra functionality,
20
+ - xarray: Used for loading image data as arrays with extra functionality,
21
21
  including labeled coordinates and metadata, which is useful for analysis and
22
22
  visualization.
23
23
  """
@@ -32,6 +32,7 @@ from .reader.image import (
32
32
  from .reader.level0 import Level0Product
33
33
  from .reader.level1 import Level1ABProduct, Level1CProduct
34
34
  from .reader.level2 import Level2AProduct
35
+ from .reader.read import read_product
35
36
 
36
37
  __all__ = [
37
38
  "Level0Product",
@@ -41,4 +42,5 @@ __all__ = [
41
42
  "image_to_dtype_range",
42
43
  "image_to_original_range",
43
44
  "image_to_uint16_range",
45
+ "read_product",
44
46
  ]
@@ -101,6 +101,17 @@ class Level0Product(ProductBase[MetadataLevel0]):
101
101
  self.data_tags[camera]["data_offset"] = offset
102
102
  self.data_tags[camera]["data_scale"] = scale
103
103
 
104
+ def __repr__(self):
105
+ """Pretty printing of the object with the most important info"""
106
+ return (
107
+ f"{self.__class__.__name__}("
108
+ f"len(self.images)={len(self.images)}, "
109
+ f"self.images[0].shape={self.images[0].shape}"
110
+ f"crs={self.images[0].rio.crs}, "
111
+ f"image_path='{self.image_path}"
112
+ ")"
113
+ )
114
+
104
115
  def __getitem__(self, camera: str) -> xarray.DataArray:
105
116
  """Return the datarray for the chosen camera."""
106
117
  return self.images[camera]
@@ -221,6 +232,15 @@ class Level0Product(ProductBase[MetadataLevel0]):
221
232
  bad_pixel_filename = f"{camera}_per_frame_cloud_mask.tif"
222
233
  return self._read_array(self.image_path / bad_pixel_filename)
223
234
 
235
+ def release_memory(self):
236
+ """Explicitely releases the memory of the `images` variable.
237
+
238
+ NOTE: this function is implemented because of a memory leak inside the Rioxarray
239
+ library that doesn't release memory properly. Only use it when the image data is
240
+ not needed anymore.
241
+ """
242
+ del self.images
243
+ self.images = None
224
244
 
225
245
  def generate_level_0_metafile():
226
246
  """Example function for reading a product and generating a metadata file from the
@@ -91,7 +91,6 @@ class Level1ABProduct(ProductBase[MetadataLevel1AB]):
91
91
  self, camera: str | None = None, per_band: bool = False
92
92
  ) -> xarray.Dataset:
93
93
  """Get the bad pixel mask associated to each camera of the L0 product
94
-
95
94
  Returns
96
95
  -------
97
96
  The bad pixel masks of the cameras
@@ -107,6 +106,16 @@ class Level1ABProduct(ProductBase[MetadataLevel1AB]):
107
106
 
108
107
  return self._read_array(self.image_path / bad_pixel_filename)
109
108
 
109
+ def release_memory(self):
110
+ """Explicitely releases the memory of the `image` variable.
111
+
112
+ NOTE: this function is implemented because of a memory leak inside the Rioxarray
113
+ library that doesn't release memory properly. Only use it when the image data is
114
+ not needed anymore.
115
+ """
116
+ del self.image
117
+ self.image = None
118
+
110
119
 
111
120
  class Level1CProduct(ProductBase[MetadataLevel1C]):
112
121
  """
@@ -151,6 +160,19 @@ class Level1CProduct(ProductBase[MetadataLevel1C]):
151
160
  rx.open_rasterio(self.image_path / "L1C.tif"),
152
161
  )
153
162
  self.data_tags = self.image.attrs
163
+ self.wavelengths = [
164
+ b.wavelength.to("nm").magnitude for b in self.metadata.image.bands
165
+ ]
166
+
167
+ def __repr__(self):
168
+ """Pretty printing of the object with the most important info"""
169
+ return (
170
+ f"{self.__class__.__name__}("
171
+ f"image.shape={self.image.shape}, "
172
+ f"image.crs={self.image.rio.crs}, "
173
+ f"wavelengths={self.wavelengths}"
174
+ f"image_path='{self.image_path})"
175
+ )
154
176
 
155
177
  def _get_data_from_sidecar(
156
178
  self, sidecar_path: Path, target_ureg: UnitRegistry | None = None
@@ -182,6 +204,16 @@ class Level1CProduct(ProductBase[MetadataLevel1C]):
182
204
 
183
205
  return metadata
184
206
 
207
+ def release_memory(self):
208
+ """Explicitely releases the memory of the `image` variable.
209
+
210
+ NOTE: this function is implemented because of a memory leak inside the Rioxarray
211
+ library that doesn't release memory properly. Only use it when the image data is
212
+ not needed anymore.
213
+ """
214
+ del self.image
215
+ self.image = None
216
+
185
217
 
186
218
  def generate_level_1_metafile():
187
219
  """Example function for reading a product and generating a metadata file from the
@@ -52,6 +52,19 @@ class Level2AProduct(ProductBase[MetadataLevel2A]):
52
52
  rx.open_rasterio(self.image_path / "L2A.tif"),
53
53
  )
54
54
  self.data_tags = self.image.attrs
55
+ self.wavelengths = [
56
+ b.wavelength.to("nm").magnitude for b in self.metadata.image.bands
57
+ ]
58
+
59
+ def __repr__(self):
60
+ """Pretty printing of the object with the most important info"""
61
+ return (
62
+ f"{self.__class__.__name__}("
63
+ f"image.shape={self.image.shape}, "
64
+ f"image.crs={self.image.rio.crs}, "
65
+ f"wavelengths={self.wavelengths}"
66
+ f"image_path='{self.image_path})"
67
+ )
55
68
 
56
69
  def _get_data_from_sidecar(
57
70
  self, sidecar_path: Path, target_ureg: UnitRegistry | None = None
@@ -83,6 +96,16 @@ class Level2AProduct(ProductBase[MetadataLevel2A]):
83
96
 
84
97
  return metadata
85
98
 
99
+ def release_memory(self):
100
+ """Explicitely releases the memory of the `image` variable.
101
+
102
+ NOTE: this function is implemented because of a memory leak inside the Rioxarray
103
+ library that doesn't release memory properly. Only use it when the image data is
104
+ not needed anymore.
105
+ """
106
+ del self.image
107
+ self.image = None
108
+
86
109
 
87
110
  def generate_level_2_metafile():
88
111
  """Example function for reading a product and generating a metadata file from the
@@ -0,0 +1,55 @@
1
+ from pathlib import Path
2
+
3
+ from kuva_reader import Level0Product, Level1ABProduct, Level1CProduct, Level2AProduct
4
+
5
+
6
+ def read_product(
7
+ product_path: Path,
8
+ ) -> Level0Product | Level1ABProduct | Level1CProduct | Level2AProduct:
9
+ """Helper function for reading any product level based on folder name or TIF name.
10
+
11
+ Parameters
12
+ ----------
13
+ product_path
14
+ Path to the product to load
15
+
16
+ Returns
17
+ -------
18
+ The product of the correct processing level
19
+
20
+ Raises
21
+ ------
22
+ ValueError
23
+ Folder not existing or files are renamed so that processing level isn't visible
24
+ """
25
+
26
+ product_map = {
27
+ "L0": Level0Product,
28
+ "L1AB": Level1ABProduct,
29
+ "L1C": Level1CProduct,
30
+ "L2A": Level2AProduct,
31
+ }
32
+
33
+ product_path = Path(product_path) # Might be a string, typing not enforced
34
+ if not product_path.is_dir():
35
+ e_ = f"Given product path is not a folder: '{product_path}'"
36
+ raise ValueError(e_)
37
+
38
+ # First check if top level filepath matches
39
+ for product_level, product_class in product_map.items():
40
+ if product_level in product_path.name:
41
+ return product_class(product_path)
42
+
43
+ # In case folder is renamed, check if tif file product level matches.
44
+ # Folder should contain one 'LXX.tif' file.
45
+ for tif_path in product_path.glob("L*.tif"):
46
+ if tif_path.stem in product_map:
47
+ return product_map[tif_path.stem](product_path)
48
+
49
+ # Folder and filenames don't match expected format
50
+ e_ = (
51
+ f"Product folder '{product_path}' does not contain the processing level "
52
+ "information. Check that you have a correct folder or consider using the "
53
+ "correct reader (L0, L1AB, L1C, L2A)."
54
+ )
55
+ raise ValueError(e_)
@@ -0,0 +1,131 @@
1
+ Metadata-Version: 2.1
2
+ Name: kuva-reader
3
+ Version: 0.1.4
4
+ Summary: Manipulate the Kuva Space image and metadata formats
5
+ License: MIT
6
+ Author: Guillem Ballesteros
7
+ Author-email: guillem@kuvaspace.com
8
+ Requires-Python: >=3.10,<=3.13
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Requires-Dist: kuva-geometry
15
+ Requires-Dist: kuva-metadata
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)
20
+ Requires-Dist: rioxarray (>=0.12.4,<0.13.0)
21
+ Requires-Dist: xarray (>=2022.12.0,<2023.0.0)
22
+ Description-Content-Type: text/markdown
23
+
24
+ <div align="center">
25
+ <picture>
26
+ <source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/1d8b44f1-1999-4cfb-8744-32871056c253">
27
+ <img alt="kuva-space-logo" src="https://github.com/user-attachments/assets/d8f47cc8-1491-4d0c-a8cf-318ea7e0afdc" width="50%">
28
+ </picture>
29
+ </div>
30
+
31
+ # Reader for Kuva Space images
32
+
33
+ The reader project allows the reading of Kuva Space products from any part of its processing chain.
34
+
35
+ The Kuva Space images are in GeoTIFF format. The products consist of an image or multiple
36
+ images along with its metadata to give all the necessary information to use the products.
37
+ The metadata lives either in a Kuva Space database, or alternatively in a sidecar JSON file.
38
+
39
+ This library allows the reading of the image GeoTIFFs into `xarray.Dataset` objects that
40
+ allow convenient raster manipulations, along with their `kuva-metadata` metadata objects.
41
+
42
+
43
+ # Table of Contents
44
+
45
+ - [Installation](#installation)
46
+ - [Code](#code)
47
+ - [Minimal example](#minimal-example)
48
+ - [Processing levels](#processing-levels)
49
+ - [Special tags](#special-tags)
50
+ - [Contributing](#contributing)
51
+ - [Configuration](#configuration)
52
+ - [Contact information](#contact-information)
53
+ - [License](#license)
54
+
55
+ # Installation
56
+
57
+ ```bash
58
+ pip install kuva-reader
59
+ ```
60
+
61
+ ### Requirements
62
+
63
+ `Python 3.10` to `3.13`, preferably within a virtual environment
64
+
65
+ # Code
66
+
67
+ ## Minimal example
68
+
69
+ This is a minimal example that allows you to read and print the image shape of a L1 product. \
70
+ The result product is in this case an L1C product (as seen from the folder name).
71
+ The loaded product is stored in a `rioxarray` object, which contains extensive GIS functionalities [(examples for usage)](https://corteva.github.io/rioxarray/stable/examples/examples.html).
72
+
73
+ ```python
74
+ from kuva_reader import read_product
75
+
76
+ l1c_product = read_product("my_data_folder/hyperfield1a_L2A_20250105T092548")
77
+ print(product) # Will show some main information such as image shape and CRS
78
+ ```
79
+
80
+ This assumes a mostly untouched folder after distributing. Otherwise, you may need to
81
+ read the product manually based on the product processing level:
82
+
83
+ ```python
84
+ from kuva_reader import Level2AProduct
85
+
86
+ l2a_product = Level2AProduct("your/l2a/folder")
87
+ ```
88
+
89
+ The actual raster image is stored and can be analysed in `product.image`, while metadata
90
+ information of the product is in `product.metadata`.
91
+
92
+ ## Processing levels
93
+
94
+ Currently the reader supports the following processing levels for Kuva products:
95
+
96
+ - **L0**: Radiometrically corrected frames as TOA radiance
97
+ - **L1AB**: Band-aligned product formed from multiple L0 products
98
+ - **L1C**: Georeferences and orthorectified L1 product
99
+ - **L2A**: Atmospherically corrected product as BOA reflectance
100
+
101
+ ## Special tags
102
+
103
+ All images generated by Kuva Space should have the following special tags added to the
104
+ geotiff metadata.
105
+ - `_KUVA_PRODUCT_LEVEL`: A string, e.g, `"0"` describing the level of the product.
106
+ - `_KUVA_PRODUCT_ID`: The id on the database for the product associated with the geotiff.
107
+
108
+ This makes it very easy to pinpoint what product we are dealing with and works around
109
+ the issue that our images are not a monolithic entity but rather just folders that can
110
+ be messed with.
111
+
112
+ # Contributing
113
+
114
+ Please follow the guidelines in [CONTRIBUTING.md](../CONTRIBUTING.md).
115
+
116
+ Also, please follow our [Code of Conduct](../CODE_OF_CONDUCT.md) while discussing in the
117
+ issues and pull requests.
118
+
119
+ # Contact information
120
+
121
+ For questions or support, please open an issue. If you have been given a support contact,
122
+ feel free to send them an email explaining your issue.
123
+
124
+ # License
125
+
126
+ The `kuva-reader` project software is under the [MIT license](../LICENSE.md).
127
+
128
+ # Status of unit tests
129
+
130
+ [![Unit tests for kuva-reader](https://github.com/KuvaSpace/kuva-data-processing/actions/workflows/test-kuva-reader.yml/badge.svg)](https://github.com/KuvaSpace/kuva-data-processing/actions/workflows/test-kuva-reader.yml)
131
+
@@ -0,0 +1,15 @@
1
+ kuva_reader/__init__.py,sha256=qqsgtVNCkqXFuXOXf5v51ZT_Dcipj1ty0mGUw8fU3sU,1509
2
+ kuva_reader/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ kuva_reader/reader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ kuva_reader/reader/image.py,sha256=Ep54Tzila3hKF2I_u-54xnFUf8WqP2fiKAJnbyZxasA,4647
5
+ kuva_reader/reader/level0.py,sha256=atehEeBnlHewRFaC0kuOGEwg7YaWnLaI9MR4OPiDveU,10233
6
+ kuva_reader/reader/level1.py,sha256=iqTsetWpPZaiM9-CjeNdyXqJrODsKFPFqCyBGrlcNY0,7693
7
+ kuva_reader/reader/level2.py,sha256=co6KOUI5PSPkGTqoKnZAxWFVsFRGOdE3PnQ5PDhmdnk,3969
8
+ kuva_reader/reader/product_base.py,sha256=_O96DACi2bWEXhNJVuIU328RJ1y1gs7_rMyyEaMo4aA,4294
9
+ kuva_reader/reader/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ kuva_reader/reader/read.py,sha256=l2x-vlOLP8AUMzqSjHLaT7xt0YJtYUjiYWm6btV-rqo,1762
11
+ kuva_reader/reader/utils.py,sha256=oZ1G43nm8lCxzfbdqBs0KhKaXWe_uf-78uBXWvmZigs,1566
12
+ kuva_reader-0.1.4.dist-info/METADATA,sha256=YZzgW8DEPaLqKreWgz28uCguDBHpNpDQVXUOvGzFkMQ,4762
13
+ kuva_reader-0.1.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
14
+ kuva_reader-0.1.4.dist-info/entry_points.txt,sha256=YJysY9EChfOb1W_IEht2oE5Z8Y9jA0J6-kofaPv-NdI,149
15
+ kuva_reader-0.1.4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.1
2
+ Generator: poetry-core 1.9.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,24 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: kuva-reader
3
- Version: 0.1.3
4
- Summary: Manipulate the Kuva Space image and metadata formats
5
- License: MIT
6
- Author: Guillem Ballesteros
7
- Author-email: guillem@kuvaspace.com
8
- Requires-Python: >=3.10,<=3.13
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
14
- Classifier: Programming Language :: Python :: 3.13
15
- Requires-Dist: dask (>=2023.12.1,<2024.0.0)
16
- Requires-Dist: kuva-geometry
17
- Requires-Dist: kuva-metadata
18
- Requires-Dist: numpy (>=1.26.4,<2.0.0)
19
- Requires-Dist: numpy-quaternion (>=2022.4.4,<2023.0.0)
20
- Requires-Dist: pint (>=0.22,<0.23)
21
- Requires-Dist: psycopg (>=3.2.3,<4.0.0)
22
- Requires-Dist: rasterio (>=1.4.1,<2.0.0)
23
- Requires-Dist: rioxarray (>=0.12.4,<0.13.0)
24
- Requires-Dist: xarray (>=2022.12.0,<2023.0.0)
@@ -1,14 +0,0 @@
1
- kuva_reader/__init__.py,sha256=ZfbIywT9FhYS3hqEMVeg0U2E8F5B-be6KTfyzO9Sz2Q,1478
2
- kuva_reader/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- kuva_reader/reader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- kuva_reader/reader/image.py,sha256=Ep54Tzila3hKF2I_u-54xnFUf8WqP2fiKAJnbyZxasA,4647
5
- kuva_reader/reader/level0.py,sha256=-5nuuxxwZDnn5Bw0--OFEiEiWz3HBFiCzOVAqczGA9k,9478
6
- kuva_reader/reader/level1.py,sha256=mN1uMMDHh8Mt6s20gCU1xH5OmcP8xM0OzfyN0VM9bL8,6487
7
- kuva_reader/reader/level2.py,sha256=k-vIvT84jvgyTBb_PmbaMMXY1wrl5v-MWqL7hV0tj1Q,3129
8
- kuva_reader/reader/product_base.py,sha256=_O96DACi2bWEXhNJVuIU328RJ1y1gs7_rMyyEaMo4aA,4294
9
- kuva_reader/reader/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- kuva_reader/reader/utils.py,sha256=oZ1G43nm8lCxzfbdqBs0KhKaXWe_uf-78uBXWvmZigs,1566
11
- kuva_reader-0.1.3.dist-info/METADATA,sha256=Kf0jEWYkhSxeQEnav-mWLM9wbGXmzwro3gSxX_GHwRc,930
12
- kuva_reader-0.1.3.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
13
- kuva_reader-0.1.3.dist-info/entry_points.txt,sha256=YJysY9EChfOb1W_IEht2oE5Z8Y9jA0J6-kofaPv-NdI,149
14
- kuva_reader-0.1.3.dist-info/RECORD,,