Skip to content

Commit bde1229

Browse files
authored
Merge pull request #15 from terrafloww/patchfix/aws_creds_issues
patch fix aws creds and add uv package manger
2 parents 482d801 + 1fb71fe commit bde1229

File tree

9 files changed

+1875
-180
lines changed

9 files changed

+1875
-180
lines changed

.github/workflows/ci.yaml

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@ on:
44
branches:
55
- main
66
paths:
7-
- requirements.txt
7+
- pyproject.toml
8+
- uv.lock
89
- 'src/**'
910
- 'examples/**'
1011
pull_request:
1112
branches:
1213
- main
1314
paths:
14-
- requirements.txt
15+
- pyproject.toml
16+
- uv.lock
1517
- 'src/**'
1618
- 'examples/**'
1719

@@ -21,32 +23,33 @@ jobs:
2123

2224
strategy:
2325
matrix:
24-
python-version: ["3.11"]
26+
python-version: ["3.10", "3.11"]
2527

2628
steps:
2729
- name: Checkout repository
2830
uses: actions/checkout@v4
2931

32+
- name: Install uv
33+
uses: astral-sh/setup-uv@v6
34+
3035
- name: Set up Python ${{ matrix.python-version }}
3136
uses: actions/setup-python@v4
3237
with:
3338
python-version: ${{ matrix.python-version }}
3439

3540
- name: Install dependencies
3641
run: |
37-
python -m pip install --upgrade pip
38-
pip install uv
39-
uv pip install -r requirements.txt --system
40-
pip install -e .[dev]
42+
uv sync --all-extras
43+
uv build
4144
4245
- name: Lint with ruff
4346
run: |
44-
ruff check .
47+
uvx ruff check .
4548
4649
- name: Format with black
4750
run: |
48-
black --check .
51+
uvx black --check .
4952
5053
- name: Run tests
5154
run: |
52-
pytest --cov=rasteret
55+
uv run pytest --cov=rasteret

examples/basic_workflow_xarray.py renamed to examples/basic_workflow_xarray_landsat_paid.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ def main():
1717
workspace_dir = Path.home() / "rasteret_workspace"
1818
workspace_dir.mkdir(exist_ok=True)
1919

20-
custom_name = "bangalore"
21-
date_range = ("2024-01-01", "2024-03-31")
20+
custom_name = "bangalore_landsat"
21+
date_range = ("2024-01-01", "2024-01-31")
2222
data_source = DataSources.LANDSAT
2323

2424
# Define area and time of interest
@@ -37,6 +37,7 @@ def main():
3737
# "bangalore_202401-03_landsat", if date_range spans across years, it will be "bangalore_202401-202503_landsat"
3838
collections = Rasteret.list_collections(workspace_dir=workspace_dir)
3939
for c in collections:
40+
print(f"Existing collection in workspace dir {workspace_dir} :")
4041
print(
4142
f"- {c['name']}: {c['data_source']}, {c['date_range']}, {c['size']} scenes"
4243
)
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# SPDX-License-Identifier: AGPL-3.0-only
2+
# Copyright 2025 Terrafloww Labs, Inc.
3+
4+
from pathlib import Path
5+
from shapely.geometry import Polygon
6+
7+
from rasteret import Rasteret
8+
from rasteret.constants import DataSources
9+
from rasteret.core.utils import save_per_geometry
10+
11+
import xarray as xr
12+
13+
aoi1_polygon = Polygon(
14+
[(77.55, 13.01), (77.58, 13.01), (77.58, 13.08), (77.55, 13.08), (77.55, 13.01)]
15+
)
16+
17+
18+
# Get the total bounds of all polygons above
19+
bbox = aoi1_polygon.bounds
20+
# OR
21+
# give even larger AOI bounds that covers all your future analysis areas
22+
# eg., Polygon of a State or a Country
23+
# bbox = country_polygon.bounds
24+
25+
# Collection configuration
26+
27+
# give your custom name for local collection, it will be attached to the
28+
# beginning of the collection name for eg., bangalore_202401-12_landsat
29+
custom_name = "bangalore"
30+
31+
# here we are aiming to write 1 year worth of STAC metadata and COG file headers to local disk
32+
date_range = ("2024-01-01", "2024-01-31")
33+
34+
# choose from LANDSAT / SENTINEL2
35+
data_source = DataSources.SENTINEL2
36+
37+
# Set up workspace folder as you wish
38+
workspace_dir = Path.home() / "rasteret_workspace"
39+
workspace_dir.mkdir(exist_ok=True)
40+
41+
# List existing collections if there are any in the workspace folder
42+
collections = Rasteret.list_collections(workspace_dir=workspace_dir)
43+
for c in collections:
44+
print(f"\nExisting Collection in workspace dir {workspace_dir}:")
45+
print(f"- {c['name']}: {c['data_source']}, {c['date_range']}, {c['size']} scenes")
46+
47+
# Try loading existing collection
48+
try:
49+
# example name given here
50+
processor = Rasteret.load_collection(
51+
"bangalore_202401-12_landsat", workspace_dir=workspace_dir
52+
)
53+
except ValueError:
54+
55+
# Instantiate the Class
56+
processor = Rasteret(
57+
workspace_dir=workspace_dir,
58+
custom_name=custom_name,
59+
data_source=data_source,
60+
date_range=date_range,
61+
)
62+
63+
# and create a new collection
64+
65+
# we are giving the BBOX for which STAC items and their COG headers will be fetched
66+
# and also filtering using PySTAC filters for LANDSAT 8 platform specifically
67+
# from LANDSAT USGS STAC, and giving a scene level cloud-cover filter
68+
processor.create_collection(
69+
bbox=bbox,
70+
cloud_cover_lt=20,
71+
)
72+
73+
# Now we can query the collection created above, to get the data we want
74+
# in this case 2 geometries, 2 bands, and a few PySTAC search filters are provided
75+
ds = processor.get_xarray(
76+
geometries=[aoi1_polygon],
77+
bands=["B04", "B08"],
78+
cloud_cover_lt=20,
79+
date_range=["2024-01-10", "2024-01-30"],
80+
)
81+
# this returns an xarray dataset variable "ds" with the data for the geometries and bands specified
82+
# behind the scenes, the library is efficiently filtering the local STAC geoparquet,
83+
# for the LANDSAT scenes that pass the filters and dates provided
84+
# then its getting the tif urls of the requested bands
85+
# then grabbing COG tiles only for the geometries from those tif files
86+
# and creating a xarray dataset for each geometry and its time series data
87+
88+
# Calculate NDVI
89+
ndvi = (ds.B08 - ds.B04) / (ds.B08 + ds.B04)
90+
91+
# for LANDSAT satellite
92+
# ndvi_ds = (ds.B5 - ds.B4) / (ds.B5 + ds.B4)
93+
94+
# give a data variable name for NDVI array
95+
ndvi_ds = xr.Dataset(
96+
{"NDVI": ndvi},
97+
coords=ds.coords,
98+
attrs=ds.attrs,
99+
)
100+
101+
# create a output folder if you wish to
102+
output_dir = Path(f"ndvi_results_{custom_name}")
103+
output_dir.mkdir(exist_ok=True)
104+
105+
# Save results from xarray to geotiff files, each geometry's data will be stored in
106+
# its own folder. We can also give file-name prefix
107+
# and also mention which Xarray varible to save as geotiffs
108+
output_files = save_per_geometry(
109+
ndvi_ds, output_dir, file_prefix="ndvi", data_var="NDVI"
110+
)
111+
112+
for geom_id, filepath in output_files.items():
113+
print(f"Geometry {geom_id}: {filepath}")

examples/example_xarray_nb.ipynb

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
},
3030
{
3131
"cell_type": "code",
32-
"execution_count": 2,
32+
"execution_count": null,
3333
"id": "d6cf7929-caed-44c2-825a-b58d5b7bec94",
3434
"metadata": {},
3535
"outputs": [],
@@ -39,22 +39,18 @@
3939
"workspace_dir.mkdir(exist_ok=True)\n",
4040
"\n",
4141
"# Define a custom name for the stac index\n",
42-
"custom_name = \"bangalore-v2\"\n",
42+
"custom_name = \"bangalore_sentinel2_nb\"\n",
4343
"\n",
4444
"# Define area, time range and data source required in stac search\n",
45-
"date_range = (\"2024-12-01\", \"2025-01-30\")\n",
46-
"data_source = DataSources.LANDSAT # or SENTINEL2\n",
45+
"date_range = (\"2025-01-01\", \"2025-01-30\")\n",
46+
"data_source = DataSources.SENTINEL2 # or SENTINEL2\n",
4747
"\n",
4848
"aoi1_polygon = Polygon(\n",
4949
" [(77.55, 13.01), (77.58, 13.01), (77.58, 13.08), (77.55, 13.08), (77.55, 13.01)]\n",
5050
")\n",
5151
"\n",
52-
"aoi2_polygon = Polygon(\n",
53-
" [(77.56, 13.02), (77.59, 13.02), (77.59, 13.09), (77.56, 13.09), (77.56, 13.02)]\n",
54-
")\n",
55-
"\n",
56-
"# get total bounds of all polygons above for stac search and stac index creation\n",
57-
"bbox = aoi1_polygon.union(aoi2_polygon).bounds\n",
52+
"# get total bounds of all polygons above for STAC search and STAC index creation\n",
53+
"bbox = aoi1_polygon.bounds\n",
5854
"\n"
5955
]
6056
},
@@ -70,6 +66,7 @@
7066
"print(\"--------------------------\")\n",
7167
"collections = Rasteret.list_collections(workspace_dir=workspace_dir)\n",
7268
"for c in collections:\n",
69+
" print(f\"Existing collection in workspace dir {workspace_dir}:\")\n",
7370
" print(f\"- {c['name']}: {c['data_source']}, {c['date_range']}, {c['size']} scenes\")"
7471
]
7572
},
@@ -81,7 +78,7 @@
8178
"outputs": [],
8279
"source": [
8380
"# You can load any existing collection in any folder\n",
84-
"processor = Rasteret.load_collection(\"bangalore_202401-01_landsat\", workspace_dir=workspace_dir)\n"
81+
"#processor = Rasteret.load_collection(\"bangalore_202401-01_landsat\", workspace_dir=workspace_dir)\n"
8582
]
8683
},
8784
{
@@ -102,8 +99,7 @@
10299
"processor.create_collection(\n",
103100
" bbox=bbox,\n",
104101
" date_range=date_range,\n",
105-
" cloud_cover_lt=20,\n",
106-
" platform={\"in\": [\"LANDSAT_8\"]}\n",
102+
" cloud_cover_lt=50,\n",
107103
")"
108104
]
109105
},
@@ -120,8 +116,9 @@
120116
"print(\"\\n3. Processing Data\")\n",
121117
"print(\"-----------------\")\n",
122118
"ds = processor.get_xarray(\n",
123-
" geometries=[aoi1_polygon, aoi2_polygon],\n",
124-
" bands=[\"B4\", \"B5\"],\n",
119+
" geometries=[aoi1_polygon],\n",
120+
" bands=[\"B04\", \"B08\"],\n",
121+
" # give more STAC specific filters if requried\n",
125122
" cloud_cover_lt=20\n",
126123
")\n",
127124
"\n",
@@ -130,13 +127,13 @@
130127
},
131128
{
132129
"cell_type": "code",
133-
"execution_count": 7,
130+
"execution_count": null,
134131
"id": "aa8f4c96-5c5f-4847-a6f3-1a1a06257312",
135132
"metadata": {},
136133
"outputs": [],
137134
"source": [
138135
"# Calculate NDVI\n",
139-
"ndvi = (ds.B5 - ds.B4) / (ds.B5 + ds.B4)\n",
136+
"ndvi = (ds.B08 - ds.B04) / (ds.B08 + ds.B04)\n",
140137
"\n",
141138
"# Create a new dataset with NDVI as a variable\n",
142139
"ndvi_ds = xr.Dataset(\n",

pyproject.toml

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,45 @@
1-
[build-system]
2-
requires = ["setuptools>=45", "wheel", "setuptools_scm>=6.2"]
3-
build-backend = "setuptools.build_meta"
1+
[project]
2+
name = "rasteret"
3+
version = "0.2.1"
4+
description = "Python library that gives you faster querying of Cloud-Optimized GeoTIFFs (COGs), and lowers S3 HTTP requests in your workflows."
5+
readme = "README.md"
6+
requires-python = ">=3.10,<3.12"
7+
authors = [
8+
{ name = "Sidharth Subramaniam", email = "sid@terrafloww.com" }
9+
]
10+
dependencies = [
11+
"numpy>=1.24.0",
12+
"pyarrow>=14.0.1",
13+
"pystac-client>=0.7.5",
14+
"stac-geoparquet==0.6.0",
15+
"aiohttp>=3.9.1",
16+
"aiofiles>=23.2.1",
17+
"cachetools>=5.3.2",
18+
"geoarrow-pyarrow>=0.1.0",
19+
"geoarrow-pandas>=0.1.0",
20+
"boto3==1.18.32",
21+
"xarray==2025.01.0",
22+
"rioxarray>=0.7.0",
23+
"imagecodecs>=2023.9.18",
24+
"zstandard>=0.22.0",
25+
"pyproj>=3.6.1",
26+
"shapely>=2.0.2",
27+
"affine>=2.4.0",
28+
"rasterio>=1.4.0",
29+
"rich>=13.7.0",
30+
"tqdm>=4.66.1",
31+
]
432

5-
[tool.black]
6-
line-length = 88
7-
include = '\.pyi?$'
8-
exclude = '''
9-
/(
10-
\.eggs
11-
| \.git
12-
| \.hg
13-
| \.mypy_cache
14-
| \.tox
15-
| \.venv
16-
| _build
17-
| buck-out
18-
| build
19-
| dist
20-
)/
21-
'''
33+
[project.optional-dependencies]
34+
dev = [
35+
"pytest>=8.4.2",
36+
"pytest-cov>=7.0.0",
37+
"black>=23.12.1",
38+
]
2239

23-
[tool.isort]
24-
profile = "black"
25-
multi_line_output = 3
26-
include_trailing_comma = true
27-
force_grid_wrap = 0
28-
use_parentheses = true
29-
ensure_newline_before_comments = true
30-
line_length = 88
40+
[project.scripts]
41+
rasteret = "rasteret:main"
3142

32-
[tool.pytest.ini_options]
33-
minversion = "6.0"
34-
addopts = "-ra -q --cov=rasteret"
35-
testpaths = [
36-
"tests",
37-
]
43+
[build-system]
44+
requires = ["hatchling"]
45+
build-backend = "hatchling.build"

0 commit comments

Comments
 (0)