Acces la date COG¶
Produsele sunt stocate ca Cloud Optimized GeoTIFF în stocarea de obiecte a
platformei. Asta înseamnă că se poate citi doar porțiunea necesară — o
previzualizare la rezoluție redusă sau o fereastră geografică — prin cereri HTTP
Range, fără a descărca produsul întreg (sute de MB).
Trei unelte, fiecare cu rolul ei:
pystac-clientgăsește produsul în catalog;eocube, biblioteca platformei, semnează legăturile către fișiere (sign_in_place) cu credențialele dumneavoastră, astfel încât orice unealtă le poate citi prin HTTPS;rioxarray/rasteriocitesc porțiunea cerută.
Aveți nevoie de un cont EOCube.Ro: pe notebooks.eocube.ro
este deja configurat; pe calculatorul propriu rulați o dată eocube auth login.
import logging
import os
# Pe hub variabila există deja; pe un calculator propriu este necesară pentru ca
# legăturile semnate să fie acceptate de stocare (eocube-tools #42).
os.environ.setdefault("AWS_DEFAULT_REGION", "ro-west-uvt-01")
logging.getLogger("eocube").setLevel(logging.ERROR)
import matplotlib.pyplot as plt
import rioxarray
from pystac_client import Client
from eocube.integrations.notebooks import setup_notebook, sign_in_place
setup_notebook() # semnarea legăturilor rulează în bucla de evenimente a kernelului
Căutare, cu legăturile semnate din start¶
Două lucruri de reținut în apelul de mai jos. modifier=sign_in_place face ca
fiecare produs întors de catalog să vină gata cu legături semnate (valabile 7
zile) în loc de adrese s3://. Iar selecția se face pe server, cu un filtru
CQL2: puțini nori și puțini
pixeli fără date (Timișoara este la marginea fâșiei orbitei 36, ale cărei
produse acoperă doar un colț al dalei). Extensia query nu este disponibilă pe
acest catalog (pgstac lucrează cu CQL2), dar filter este.
catalog = Client.open("https://stac.eocube.ro", modifier=sign_in_place)
item = next(catalog.search(
collections=["sentinel-2-l2a"],
intersects={"type": "Point", "coordinates": [21.23, 45.75]}, # Timișoara
filter={"op": "and", "args": [
{"op": "<", "args": [{"property": "eo:cloud_cover"}, 5]},
{"op": "<", "args": [{"property": "s2:nodata_pixel_percentage"}, 10]}, # nu la marginea fâșiei
]},
sortby=[{"field": "properties.datetime", "direction": "desc"}],
max_items=1,
).items())
print(item.id)
print(f"data: {item.datetime:%Y-%m-%d} nori: {item.properties['eo:cloud_cover']:.1f}%")
S2B_MSIL2A_20260927T093029_N9999_R136_T34TER.SAFE data: 2026-09-27 nori: 2.1%
Legătura semnată este un URL HTTPS obișnuit, cu semnătura în parametrii de
interogare (o afișăm fără ei). Se poate deschide direct în QGIS, gdalinfo sau
un browser, câtă vreme nu a expirat.
vizual = item.assets["visual"].href
print(vizual.split("?")[0].replace("https://", "…"), "?<semnătură>")
…storage.svc.uvt-01.eocube.ro/sentinel-2-l2a/Sentinel-2/MSI/L2A/2026/09/27/S2B_MSIL2A_20260927T093029_N9999_R136_T34TER.SAFE/GRANULE/L2A_T34TER_A049926_20260927T093429/IMG_DATA/R10m/T34TER_20260927T093029_VISUAL_10m.tif ?<semnătură>
Citire parțială: doar o previzualizare¶
overview_level folosește piramidele interne ale COG-ului: se transferă câțiva
megaocteți în loc de tot fișierul.
da = rioxarray.open_rasterio(vizual, overview_level=2, masked=True)
print(da.rio.crs, "| formă:", da.shape, "| rezoluție:", [round(r) for r in da.rio.resolution()])
da
EPSG:32634 | formă: (3, 1372, 1372) | rezoluție: [80, -80]
<xarray.DataArray (band: 3, y: 1372, x: 1372)> Size: 23MB
[5647152 values with dtype=float32]
Coordinates:
* band (band) int64 24B 1 2 3
* y (y) float64 11kB 5.1e+06 5.1e+06 5.1e+06 ... 4.99e+06 4.99e+06
* x (x) float64 11kB 5e+05 5.001e+05 ... 6.097e+05 6.097e+05
spatial_ref int64 8B 0
Attributes:
TIFFTAG_IMAGEDESCRIPTION: Enhanced true-colour visual (relief-reshaded, ...
TIFFTAG_SOFTWARE: Sen2Cor 2.12.03; GDAL 3.6.2; sen2cor-service 0...
TIFFTAG_ARTIST: West University of Timisoara on behalf of the ...
TIFFTAG_COPYRIGHT: Copernicus Sentinel data 2026 (c) ESA. Contain...
AREA_OR_POINT: Area
scale_factor: 1.0
add_offset: 0.0rgb = da.transpose("y", "x", "band").values / 255.0
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(rgb)
ax.set_axis_off()
ax.set_title(f"{item.id[:38]}\ncompozit true-color (overview)", fontsize=9)
plt.tight_layout(); plt.show()
Citire parțială: o fereastră la rezoluție întreagă¶
Al doilea mod de a citi puțin: o fereastră geografică, la 10 m. Deschiderea este
leneșă; clip_box primește colțurile în coordonate geografice și doar pixelii
din fereastră se transferă atunci când îi cerem.
fereastra = (
rioxarray.open_rasterio(vizual, masked=True)
.rio.clip_box(21.15, 45.70, 21.30, 45.80, crs="EPSG:4326") # centrul Timișoarei
)
print("formă:", fereastra.shape, "| rezoluție:", [round(r) for r in fereastra.rio.resolution()])
fig, ax = plt.subplots(figsize=(8, 6))
ax.imshow(fereastra.transpose("y", "x", "band").values / 255.0)
ax.set_axis_off(); ax.set_title("Timișoara la 10 m, citită direct din COG", fontsize=10)
plt.tight_layout(); plt.show()
Un indice spectral, tot din citiri parțiale¶
NDVI din benzile roșu (B04) și infraroșu apropiat (B08), la 10 m, citite la nivel de overview. Legăturile benzilor sunt deja semnate, ca toate asset-urile produsului.
red = rioxarray.open_rasterio(item.assets["B04_10m"].href, overview_level=2, masked=True).squeeze()
nir = rioxarray.open_rasterio(item.assets["B08_10m"].href, overview_level=2, masked=True).squeeze()
ndvi = (nir - red) / (nir + red)
fig, ax = plt.subplots(figsize=(7, 6))
ndvi.plot.imshow(ax=ax, cmap="RdYlGn", vmin=-0.2, vmax=0.9, add_colorbar=True)
ax.set_axis_off(); ax.set_title("NDVI", fontsize=10)
plt.tight_layout(); plt.show()
Ce urmează¶
- Aceleași legături semnate merg în orice bibliotecă care citește GeoTIFF prin
HTTP:
rasterio, GDAL, QGIS,stackstac. - Colecțiile private se caută și se citesc la fel —
sign_in_placesemnează cu drepturile contului dumneavoastră. - Procesare la scară:
setup_personal_clusterdineocubepornește un cluster Dask în platformă; vedeți Clima României pe hartă.