easy-eo 0.3.0__tar.gz → 0.3.1__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.
Files changed (42) hide show
  1. {easy_eo-0.3.0 → easy_eo-0.3.1}/.gitignore +6 -0
  2. {easy_eo-0.3.0 → easy_eo-0.3.1}/PKG-INFO +35 -9
  3. {easy_eo-0.3.0 → easy_eo-0.3.1}/README.md +32 -7
  4. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/__init__.py +1 -1
  5. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/core/core.pyi +5 -0
  6. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/datasets/_registry.py +42 -3
  7. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/datasets/_samples.py +6 -0
  8. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/viz/plot.py +53 -10
  9. {easy_eo-0.3.0 → easy_eo-0.3.1}/pyproject.toml +2 -1
  10. {easy_eo-0.3.0 → easy_eo-0.3.1}/LICENSE +0 -0
  11. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/_optional.py +0 -0
  12. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/_show_versions.py +0 -0
  13. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/analysis/__init__.py +0 -0
  14. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/analysis/indices.py +0 -0
  15. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/analysis/stats.py +0 -0
  16. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/common.py +0 -0
  17. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/core/__init__.py +0 -0
  18. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/core/adapters/__init__.py +0 -0
  19. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/core/adapters/base.py +0 -0
  20. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/core/adapters/numpy.py +0 -0
  21. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/core/adapters/rasterio.py +0 -0
  22. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/core/core.py +0 -0
  23. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/core/decorators.py +0 -0
  24. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/core/exceptions.py +0 -0
  25. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/core/loader.py +0 -0
  26. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/core/plugins.py +0 -0
  27. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/core/types.py +0 -0
  28. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/datasets/__init__.py +0 -0
  29. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/datasets/_cache.py +0 -0
  30. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/io/__init__.py +0 -0
  31. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/io/stac.py +0 -0
  32. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/io/xarray.py +0 -0
  33. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/ops/__init__.py +0 -0
  34. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/ops/algebra.py +0 -0
  35. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/ops/merge.py +0 -0
  36. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/preprocessing/__init__.py +0 -0
  37. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/preprocessing/clip.py +0 -0
  38. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/preprocessing/normalize.py +0 -0
  39. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/preprocessing/reproject.py +0 -0
  40. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/preprocessing/resample.py +0 -0
  41. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/py.typed +0 -0
  42. {easy_eo-0.3.0 → easy_eo-0.3.1}/eeo/viz/__init__.py +0 -0
@@ -21,6 +21,12 @@ others/
21
21
  # Docs
22
22
  docs/build/
23
23
 
24
+ # Generated by the dependency-audit, release, and linkcheck workflows
25
+ # (and by running any of them locally)
26
+ requirements-audit.txt
27
+ .smoke-venv/
28
+ .linkcheck/
29
+
24
30
  # Tests
25
31
  .pytest_cache/
26
32
  .ruff_cache/
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: easy-eo
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: A lightweight Earth Observation utilities library for chainable raster operations
5
5
  Project-URL: Homepage, https://github.com/tommy-burns/easy-eo
6
6
  Project-URL: Repository, https://github.com/tommy-burns/easy-eo
@@ -40,6 +40,7 @@ Classifier: Programming Language :: Python :: 3.12
40
40
  Classifier: Programming Language :: Python :: 3.13
41
41
  Classifier: Programming Language :: Python :: 3.14
42
42
  Classifier: Topic :: Scientific/Engineering :: GIS
43
+ Classifier: Typing :: Typed
43
44
  Requires-Python: >=3.10
44
45
  Requires-Dist: geopandas<2,>=1.1
45
46
  Requires-Dist: matplotlib>=3.8
@@ -65,13 +66,38 @@ Description-Content-Type: text/markdown
65
66
  <img src="https://raw.githubusercontent.com/Tommy-Burns/easy-eo/main/.github/assets/eeo_logo.png" alt="Easy-EO logo" width="200">
66
67
  </p>
67
68
 
68
- [![CI](https://github.com/Tommy-Burns/easy-eo/actions/workflows/ci.yml/badge.svg)](https://github.com/Tommy-Burns/easy-eo/actions/workflows/ci.yml)
69
- [![codecov](https://codecov.io/gh/Tommy-Burns/easy-eo/branch/main/graph/badge.svg)](https://codecov.io/gh/Tommy-Burns/easy-eo)
70
- [![PyPI](https://img.shields.io/pypi/v/easy-eo.svg)](https://pypi.org/project/easy-eo/)
71
- [![conda-forge](https://img.shields.io/conda/vn/conda-forge/easy-eo.svg)](https://anaconda.org/conda-forge/easy-eo)
72
- [![Python versions](https://img.shields.io/pypi/pyversions/easy-eo.svg)](https://pypi.org/project/easy-eo/)
73
- [![Documentation Status](https://readthedocs.org/projects/easy-eo/badge/?version=latest)](https://easy-eo.readthedocs.io/en/latest/?badge=latest)
74
- [![License: MIT](https://img.shields.io/github/license/Tommy-Burns/easy-eo)](https://github.com/Tommy-Burns/easy-eo/blob/main/LICENSE)
69
+ | | |
70
+ | :-- | :-- |
71
+ | **Install** | [![PyPI][pypi-badge]][pypi] [![conda-forge][conda-badge]][conda] [![Python versions][pyversions-badge]][pypi] [![Platforms][platforms-badge]][ci] |
72
+ | **Build & quality** | [![CI][ci-badge]][ci] [![Latest deps][latest-deps-badge]][latest-deps] [![Coverage][codecov-badge]][codecov] [![Ruff][ruff-badge]][ruff] [![Checked with mypy][mypy-badge]][mypy] |
73
+ | **Security** | [![CodeQL][codeql-badge]][codeql] [![OpenSSF Scorecard][scorecard-badge]][scorecard] |
74
+ | **Project** | [![Documentation][docs-badge]][docs] [![License: MIT][license-badge]][license] |
75
+
76
+ [pypi]: https://pypi.org/project/easy-eo/
77
+ [pypi-badge]: https://img.shields.io/pypi/v/easy-eo.svg
78
+ [conda]: https://anaconda.org/conda-forge/easy-eo
79
+ [conda-badge]: https://img.shields.io/conda/vn/conda-forge/easy-eo.svg
80
+ [pyversions-badge]: https://img.shields.io/pypi/pyversions/easy-eo.svg
81
+ [platforms-badge]: https://img.shields.io/badge/platform-linux%20%7C%20macOS%20%7C%20windows-lightgrey.svg
82
+ [ci]: https://github.com/Tommy-Burns/easy-eo/actions/workflows/ci.yml
83
+ [ci-badge]: https://github.com/Tommy-Burns/easy-eo/actions/workflows/ci.yml/badge.svg
84
+ [latest-deps]: https://github.com/Tommy-Burns/easy-eo/actions/workflows/latest-deps.yml
85
+ [latest-deps-badge]: https://github.com/Tommy-Burns/easy-eo/actions/workflows/latest-deps.yml/badge.svg
86
+ [codecov]: https://codecov.io/gh/Tommy-Burns/easy-eo
87
+ [codecov-badge]: https://codecov.io/gh/Tommy-Burns/easy-eo/branch/main/graph/badge.svg
88
+ [ruff]: https://github.com/astral-sh/ruff
89
+ [ruff-badge]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
90
+ [mypy]: https://mypy-lang.org/
91
+ [mypy-badge]: https://img.shields.io/badge/mypy-checked-2a6db2.svg
92
+ [codeql]: https://github.com/Tommy-Burns/easy-eo/actions/workflows/codeql.yml
93
+ [codeql-badge]: https://github.com/Tommy-Burns/easy-eo/actions/workflows/codeql.yml/badge.svg
94
+ [scorecard]: https://scorecard.dev/viewer/?uri=github.com/Tommy-Burns/easy-eo
95
+ [scorecard-badge]: https://api.scorecard.dev/projects/github.com/Tommy-Burns/easy-eo/badge
96
+ [docs]: https://easy-eo.readthedocs.io/en/latest/?badge=latest
97
+ [docs-badge]: https://readthedocs.org/projects/easy-eo/badge/?version=latest
98
+ [license]: https://github.com/Tommy-Burns/easy-eo/blob/main/LICENSE
99
+ [license-badge]: https://img.shields.io/github/license/Tommy-Burns/easy-eo
100
+
75
101
 
76
102
  Easy-EO is a lightweight, extensible Python library for raster-based Earth
77
103
  Observation (EO) analysis: chainable raster processing, band algebra, spectral indices,
@@ -4,13 +4,38 @@
4
4
  <img src="https://raw.githubusercontent.com/Tommy-Burns/easy-eo/main/.github/assets/eeo_logo.png" alt="Easy-EO logo" width="200">
5
5
  </p>
6
6
 
7
- [![CI](https://github.com/Tommy-Burns/easy-eo/actions/workflows/ci.yml/badge.svg)](https://github.com/Tommy-Burns/easy-eo/actions/workflows/ci.yml)
8
- [![codecov](https://codecov.io/gh/Tommy-Burns/easy-eo/branch/main/graph/badge.svg)](https://codecov.io/gh/Tommy-Burns/easy-eo)
9
- [![PyPI](https://img.shields.io/pypi/v/easy-eo.svg)](https://pypi.org/project/easy-eo/)
10
- [![conda-forge](https://img.shields.io/conda/vn/conda-forge/easy-eo.svg)](https://anaconda.org/conda-forge/easy-eo)
11
- [![Python versions](https://img.shields.io/pypi/pyversions/easy-eo.svg)](https://pypi.org/project/easy-eo/)
12
- [![Documentation Status](https://readthedocs.org/projects/easy-eo/badge/?version=latest)](https://easy-eo.readthedocs.io/en/latest/?badge=latest)
13
- [![License: MIT](https://img.shields.io/github/license/Tommy-Burns/easy-eo)](https://github.com/Tommy-Burns/easy-eo/blob/main/LICENSE)
7
+ | | |
8
+ | :-- | :-- |
9
+ | **Install** | [![PyPI][pypi-badge]][pypi] [![conda-forge][conda-badge]][conda] [![Python versions][pyversions-badge]][pypi] [![Platforms][platforms-badge]][ci] |
10
+ | **Build & quality** | [![CI][ci-badge]][ci] [![Latest deps][latest-deps-badge]][latest-deps] [![Coverage][codecov-badge]][codecov] [![Ruff][ruff-badge]][ruff] [![Checked with mypy][mypy-badge]][mypy] |
11
+ | **Security** | [![CodeQL][codeql-badge]][codeql] [![OpenSSF Scorecard][scorecard-badge]][scorecard] |
12
+ | **Project** | [![Documentation][docs-badge]][docs] [![License: MIT][license-badge]][license] |
13
+
14
+ [pypi]: https://pypi.org/project/easy-eo/
15
+ [pypi-badge]: https://img.shields.io/pypi/v/easy-eo.svg
16
+ [conda]: https://anaconda.org/conda-forge/easy-eo
17
+ [conda-badge]: https://img.shields.io/conda/vn/conda-forge/easy-eo.svg
18
+ [pyversions-badge]: https://img.shields.io/pypi/pyversions/easy-eo.svg
19
+ [platforms-badge]: https://img.shields.io/badge/platform-linux%20%7C%20macOS%20%7C%20windows-lightgrey.svg
20
+ [ci]: https://github.com/Tommy-Burns/easy-eo/actions/workflows/ci.yml
21
+ [ci-badge]: https://github.com/Tommy-Burns/easy-eo/actions/workflows/ci.yml/badge.svg
22
+ [latest-deps]: https://github.com/Tommy-Burns/easy-eo/actions/workflows/latest-deps.yml
23
+ [latest-deps-badge]: https://github.com/Tommy-Burns/easy-eo/actions/workflows/latest-deps.yml/badge.svg
24
+ [codecov]: https://codecov.io/gh/Tommy-Burns/easy-eo
25
+ [codecov-badge]: https://codecov.io/gh/Tommy-Burns/easy-eo/branch/main/graph/badge.svg
26
+ [ruff]: https://github.com/astral-sh/ruff
27
+ [ruff-badge]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
28
+ [mypy]: https://mypy-lang.org/
29
+ [mypy-badge]: https://img.shields.io/badge/mypy-checked-2a6db2.svg
30
+ [codeql]: https://github.com/Tommy-Burns/easy-eo/actions/workflows/codeql.yml
31
+ [codeql-badge]: https://github.com/Tommy-Burns/easy-eo/actions/workflows/codeql.yml/badge.svg
32
+ [scorecard]: https://scorecard.dev/viewer/?uri=github.com/Tommy-Burns/easy-eo
33
+ [scorecard-badge]: https://api.scorecard.dev/projects/github.com/Tommy-Burns/easy-eo/badge
34
+ [docs]: https://easy-eo.readthedocs.io/en/latest/?badge=latest
35
+ [docs-badge]: https://readthedocs.org/projects/easy-eo/badge/?version=latest
36
+ [license]: https://github.com/Tommy-Burns/easy-eo/blob/main/LICENSE
37
+ [license-badge]: https://img.shields.io/github/license/Tommy-Burns/easy-eo
38
+
14
39
 
15
40
  Easy-EO is a lightweight, extensible Python library for raster-based Earth
16
41
  Observation (EO) analysis: chainable raster processing, band algebra, spectral indices,
@@ -38,4 +38,4 @@ __all__ = [
38
38
  "MissingDependencyError",
39
39
  ]
40
40
 
41
- __version__ = "0.3.0"
41
+ __version__ = "0.3.1"
@@ -227,6 +227,7 @@ class EEORasterDataset:
227
227
  colorbar_label: str | None = ...,
228
228
  title: str | None = ...,
229
229
  save_path: StrPath | None = ...,
230
+ dpi: int = ...,
230
231
  **imshow_kwargs,
231
232
  ) -> None: ...
232
233
  def plot_composite(
@@ -239,6 +240,7 @@ class EEORasterDataset:
239
240
  pmax: float = ...,
240
241
  title: str | None = ...,
241
242
  save_path: StrPath | None = ...,
243
+ dpi: int = ...,
242
244
  ) -> None: ...
243
245
  def plot_histogram(
244
246
  self,
@@ -251,6 +253,7 @@ class EEORasterDataset:
251
253
  log: bool = ...,
252
254
  title: str | None = ...,
253
255
  save_path: StrPath | None = ...,
256
+ dpi: int = ...,
254
257
  **hist_kwargs,
255
258
  ) -> None: ...
256
259
  def plot_raster(
@@ -268,6 +271,7 @@ class EEORasterDataset:
268
271
  colorbar_label: str | None = ...,
269
272
  title: str | None = ...,
270
273
  save_path: StrPath | None = ...,
274
+ dpi: int = ...,
271
275
  **show_kwargs,
272
276
  ) -> None: ...
273
277
  def plot_raster_with_histogram(
@@ -283,6 +287,7 @@ class EEORasterDataset:
283
287
  colorbar: bool = ...,
284
288
  colorbar_label: str | None = ...,
285
289
  save_path: StrPath | None = ...,
290
+ dpi: int = ...,
286
291
  title: str | None = ...,
287
292
  ) -> None: ...
288
293
  def power(self, exponent: int | float) -> EEORasterDataset: ...
@@ -77,9 +77,8 @@ class SampleFile:
77
77
  #: The curated samples, keyed by the attribute name they are exposed under on
78
78
  #: :class:`eeo.datasets.SampleDataset`. Band files use the library's colour band
79
79
  #: names. This is the single source of truth for both the download machinery and
80
- #: the namespace attributes. Per-band Cloud-Optimized GeoTIFFs are intentionally
81
- #: absent: only the stacked COG has a checksum pinned today, and fabricating one
82
- #: would defeat the download verification.
80
+ #: the namespace attributes. Every raster published on the release has both a
81
+ #: plain and a Cloud-Optimized variant here, the latter suffixed ``_cog``.
83
82
  SAMPLE_FILES: dict[str, SampleFile] = {
84
83
  "sentinel2_stacked": SampleFile(
85
84
  Asset(
@@ -111,6 +110,16 @@ SAMPLE_FILES: dict[str, SampleFile] = {
111
110
  "Sentinel-2 L2A band B02 (blue), 1024x1024 @ 10 m, EPSG:32633.",
112
111
  _S2_ATTRIBUTION,
113
112
  ),
113
+ "sentinel2_blue_cog": SampleFile(
114
+ Asset(
115
+ "B02_COG.tif",
116
+ "555f6fb67522148c05d7bb9a4f49d157cde2d9da00d1304ed953bfd383c9ead1",
117
+ 2293197,
118
+ ),
119
+ "raster",
120
+ "Cloud-Optimized GeoTIFF variant of the blue band (B02).",
121
+ _S2_ATTRIBUTION,
122
+ ),
114
123
  "sentinel2_green": SampleFile(
115
124
  Asset(
116
125
  "B03.tif",
@@ -121,6 +130,16 @@ SAMPLE_FILES: dict[str, SampleFile] = {
121
130
  "Sentinel-2 L2A band B03 (green), 1024x1024 @ 10 m, EPSG:32633.",
122
131
  _S2_ATTRIBUTION,
123
132
  ),
133
+ "sentinel2_green_cog": SampleFile(
134
+ Asset(
135
+ "B03_COG.tif",
136
+ "0f0e6cd16141725fe4dfd749a911f3846429b0cd7c222d543d90848ac1f95833",
137
+ 2404804,
138
+ ),
139
+ "raster",
140
+ "Cloud-Optimized GeoTIFF variant of the green band (B03).",
141
+ _S2_ATTRIBUTION,
142
+ ),
124
143
  "sentinel2_red": SampleFile(
125
144
  Asset(
126
145
  "B04.tif",
@@ -131,6 +150,16 @@ SAMPLE_FILES: dict[str, SampleFile] = {
131
150
  "Sentinel-2 L2A band B04 (red), 1024x1024 @ 10 m, EPSG:32633.",
132
151
  _S2_ATTRIBUTION,
133
152
  ),
153
+ "sentinel2_red_cog": SampleFile(
154
+ Asset(
155
+ "B04_COG.tif",
156
+ "5781624003c04ae978196df98dd54e742fe38d1bd5b56237ffc4162209eafc28",
157
+ 2436025,
158
+ ),
159
+ "raster",
160
+ "Cloud-Optimized GeoTIFF variant of the red band (B04).",
161
+ _S2_ATTRIBUTION,
162
+ ),
134
163
  "sentinel2_nir": SampleFile(
135
164
  Asset(
136
165
  "B08.tif",
@@ -141,6 +170,16 @@ SAMPLE_FILES: dict[str, SampleFile] = {
141
170
  "Sentinel-2 L2A band B08 (nir), 1024x1024 @ 10 m, EPSG:32633.",
142
171
  _S2_ATTRIBUTION,
143
172
  ),
173
+ "sentinel2_nir_cog": SampleFile(
174
+ Asset(
175
+ "B08_COG.tif",
176
+ "1488f68cad9f37a90ffef9eb62716e2cab77bd7c22954a08e2f2a5d06ce4014d",
177
+ 2504710,
178
+ ),
179
+ "raster",
180
+ "Cloud-Optimized GeoTIFF variant of the nir band (B08).",
181
+ _S2_ATTRIBUTION,
182
+ ),
144
183
  "copernicus_dem": SampleFile(
145
184
  Asset(
146
185
  "DEM.tif",
@@ -144,6 +144,8 @@ class SampleDataset:
144
144
  Cloud-Optimized GeoTIFF variant of ``sentinel2_stacked``.
145
145
  sentinel2_blue, sentinel2_green, sentinel2_red, sentinel2_nir : SamplePath
146
146
  The four Sentinel-2 bands as separate single-band GeoTIFFs.
147
+ sentinel2_blue_cog, sentinel2_green_cog, sentinel2_red_cog, sentinel2_nir_cog : SamplePath
148
+ Cloud-Optimized GeoTIFF variants of the four single-band files.
147
149
  copernicus_dem : SamplePath
148
150
  Copernicus GLO-30 DEM warped onto the Sentinel-2 grid (float32 metres).
149
151
  copernicus_dem_cog : SamplePath
@@ -156,9 +158,13 @@ class SampleDataset:
156
158
  sentinel2_stacked: SamplePath
157
159
  sentinel2_cog_stacked: SamplePath
158
160
  sentinel2_blue: SamplePath
161
+ sentinel2_blue_cog: SamplePath
159
162
  sentinel2_green: SamplePath
163
+ sentinel2_green_cog: SamplePath
160
164
  sentinel2_red: SamplePath
165
+ sentinel2_red_cog: SamplePath
161
166
  sentinel2_nir: SamplePath
167
+ sentinel2_nir_cog: SamplePath
162
168
  copernicus_dem: SamplePath
163
169
  copernicus_dem_cog: SamplePath
164
170
  boundary: SamplePath
@@ -564,6 +564,7 @@ def plot_band_array(
564
564
  colorbar_label: str | None = None,
565
565
  title: str | None = None,
566
566
  save_path: StrPath | None = None,
567
+ dpi: int = 300,
567
568
  **imshow_kwargs,
568
569
  ) -> None:
569
570
  """Plot raster bands as arrays in row/column (pixel) space.
@@ -614,7 +615,15 @@ def plot_band_array(
614
615
  title : str or None, default None
615
616
  Optional figure title.
616
617
  save_path : str or path-like or None, default None
617
- If given, save the figure to this path at 300 dpi.
618
+ If given, save the figure to this path, at ``dpi``.
619
+ dpi : int, default 300
620
+ Resolution of the saved file, in dots per inch; ignored when
621
+ ``save_path`` is None. The default suits print, but multiplies with
622
+ ``figsize``: a 15x5 figure lands near 4500x1500 pixels and well over
623
+ 10 MB, so lower it (100-150) for a figure committed to a
624
+ repository or embedded in a web page. Raising it past roughly 200
625
+ enlarges the canvas without adding detail, because bands are read at
626
+ the on-screen display budget (see Notes), not at ``dpi``.
618
627
  **imshow_kwargs
619
628
  Extra keyword arguments forwarded to ``matplotlib.pyplot.imshow``. An
620
629
  explicit ``vmin``/``vmax`` takes precedence over the stretch.
@@ -671,7 +680,7 @@ def plot_band_array(
671
680
  plt.tight_layout()
672
681
 
673
682
  if save_path is not None:
674
- plt.savefig(save_path, dpi=300, bbox_inches="tight")
683
+ plt.savefig(save_path, dpi=dpi, bbox_inches="tight")
675
684
  plt.show()
676
685
  plt.close()
677
686
 
@@ -693,6 +702,7 @@ def plot_raster(
693
702
  colorbar_label: str | None = None,
694
703
  title: str | None = None,
695
704
  save_path: StrPath | None = None,
705
+ dpi: int = 300,
696
706
  **show_kwargs,
697
707
  ) -> None:
698
708
  """Plot raster bands in spatial (CRS-aware) coordinates.
@@ -743,7 +753,15 @@ def plot_raster(
743
753
  title : str or None, default None
744
754
  Optional figure title.
745
755
  save_path : str or path-like or None, default None
746
- If given, save the figure to this path at 300 dpi.
756
+ If given, save the figure to this path, at ``dpi``.
757
+ dpi : int, default 300
758
+ Resolution of the saved file, in dots per inch; ignored when
759
+ ``save_path`` is None. The default suits print, but multiplies with
760
+ ``figsize``: a 15x5 figure lands near 4500x1500 pixels and well over
761
+ 10 MB, so lower it (100-150) for a figure committed to a
762
+ repository or embedded in a web page. Raising it past roughly 200
763
+ enlarges the canvas without adding detail, because bands are read at
764
+ the on-screen display budget (see Notes), not at ``dpi``.
747
765
  **show_kwargs
748
766
  Extra keyword arguments forwarded to ``rasterio.plot.show``. An
749
767
  explicit ``vmin``/``vmax`` takes precedence over the stretch.
@@ -807,7 +825,7 @@ def plot_raster(
807
825
 
808
826
  plt.tight_layout()
809
827
  if save_path is not None:
810
- plt.savefig(save_path, dpi=300, bbox_inches="tight")
828
+ plt.savefig(save_path, dpi=dpi, bbox_inches="tight")
811
829
  plt.show()
812
830
  plt.close()
813
831
 
@@ -825,6 +843,7 @@ def plot_histogram(
825
843
  log: bool = False,
826
844
  title: str | None = None,
827
845
  save_path: StrPath | None = None,
846
+ dpi: int = 300,
828
847
  **hist_kwargs,
829
848
  ) -> None:
830
849
  """Plot per-band value histograms.
@@ -859,7 +878,13 @@ def plot_histogram(
859
878
  title : str or None, default None
860
879
  Optional figure title.
861
880
  save_path : str or path-like or None, default None
862
- If given, save the figure to this path at 300 dpi.
881
+ If given, save the figure to this path, at ``dpi``.
882
+ dpi : int, default 300
883
+ Resolution of the saved file, in dots per inch; ignored when
884
+ ``save_path`` is None. The default suits print, but multiplies with
885
+ ``figsize``: a 15x5 figure lands near 4500x1500 pixels and well over
886
+ 10 MB, so lower it (100-150) for a figure committed to a
887
+ repository or embedded in a web page.
863
888
  **hist_kwargs
864
889
  Extra keyword arguments forwarded to ``matplotlib.pyplot.hist``.
865
890
 
@@ -904,7 +929,7 @@ def plot_histogram(
904
929
 
905
930
  plt.tight_layout()
906
931
  if save_path is not None:
907
- plt.savefig(save_path, dpi=300, bbox_inches="tight")
932
+ plt.savefig(save_path, dpi=dpi, bbox_inches="tight")
908
933
  plt.show()
909
934
  plt.close()
910
935
 
@@ -924,6 +949,7 @@ def plot_raster_with_histogram(
924
949
  colorbar: bool = False,
925
950
  colorbar_label: str | None = None,
926
951
  save_path: StrPath | None = None,
952
+ dpi: int = 300,
927
953
  title: str | None = None,
928
954
  ) -> None:
929
955
  """Plot each band alongside its value histogram.
@@ -960,7 +986,15 @@ def plot_raster_with_histogram(
960
986
  Label for the colorbars; None uses each band's name, leaving an
961
987
  unnamed band's colorbar unlabelled.
962
988
  save_path : str or path-like or None, default None
963
- If given, save the figure to this path at 300 dpi.
989
+ If given, save the figure to this path, at ``dpi``.
990
+ dpi : int, default 300
991
+ Resolution of the saved file, in dots per inch; ignored when
992
+ ``save_path`` is None. The default suits print, but multiplies with
993
+ ``figsize``: a 15x5 figure lands near 4500x1500 pixels and well over
994
+ 10 MB, so lower it (100-150) for a figure committed to a
995
+ repository or embedded in a web page. Past roughly 200 the histogram
996
+ panel keeps sharpening but the image panel does not, because bands are
997
+ read at the on-screen display budget (see Notes), not at ``dpi``.
964
998
  title : str or None, default None
965
999
  Optional figure title.
966
1000
 
@@ -1026,7 +1060,7 @@ def plot_raster_with_histogram(
1026
1060
 
1027
1061
  plt.tight_layout()
1028
1062
  if save_path is not None:
1029
- plt.savefig(save_path, dpi=300, bbox_inches="tight")
1063
+ plt.savefig(save_path, dpi=dpi, bbox_inches="tight")
1030
1064
  plt.show()
1031
1065
  plt.close()
1032
1066
 
@@ -1043,6 +1077,7 @@ def plot_composite(
1043
1077
  pmax: float = 98,
1044
1078
  title: str | None = None,
1045
1079
  save_path: StrPath | None = None,
1080
+ dpi: int = 300,
1046
1081
  ) -> None:
1047
1082
  """Plot a three-band RGB (or false-colour) composite.
1048
1083
 
@@ -1070,7 +1105,15 @@ def plot_composite(
1070
1105
  title : str or None, default None
1071
1106
  Optional figure title.
1072
1107
  save_path : str or path-like or None, default None
1073
- If given, save the figure to this path at 300 dpi.
1108
+ If given, save the figure to this path, at ``dpi``.
1109
+ dpi : int, default 300
1110
+ Resolution of the saved file, in dots per inch; ignored when
1111
+ ``save_path`` is None. The default suits print, but multiplies with
1112
+ ``figsize``: a 15x5 figure lands near 4500x1500 pixels and well over
1113
+ 10 MB, so lower it (100-150) for a figure committed to a
1114
+ repository or embedded in a web page. Raising it past roughly 200
1115
+ enlarges the canvas without adding detail, because bands are read at
1116
+ the on-screen display budget (see Notes), not at ``dpi``.
1074
1117
 
1075
1118
  Returns
1076
1119
  -------
@@ -1138,7 +1181,7 @@ def plot_composite(
1138
1181
 
1139
1182
  plt.tight_layout()
1140
1183
  if save_path is not None:
1141
- plt.savefig(save_path, dpi=300, bbox_inches="tight")
1184
+ plt.savefig(save_path, dpi=dpi, bbox_inches="tight")
1142
1185
 
1143
1186
  plt.show()
1144
1187
  plt.close()
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "easy-eo"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  description = "A lightweight Earth Observation utilities library for chainable raster operations"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -26,6 +26,7 @@ classifiers = [
26
26
  "Programming Language :: Python :: 3.13",
27
27
  "Programming Language :: Python :: 3.14",
28
28
  "Topic :: Scientific/Engineering :: GIS",
29
+ "Typing :: Typed",
29
30
  ]
30
31
 
31
32
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes