landvex: Fixar och tester klara för alla komponenter

- Datafabrik: Dockerfile fix, agentorkestrering fungerar
- Vision: Identify-modell, FAISS, OCR alla testade
- API: Alla 7 integrationstester passerade
- Upplösare: Entitetsupplösning verifierad
This commit is contained in:
Bernt
2026-07-05 06:41:32 +00:00
parent f4f853d94b
commit aee0f09db8
19583 changed files with 1450867 additions and 1153 deletions
+48
View File
@@ -0,0 +1,48 @@
{
"statistics": {
"mean_difference": 1.9875,
"max_difference": 120.0,
"std_difference": 14.63129672141195,
"changed_pixels": 3000,
"total_pixels": 160000,
"change_percentage": 1.875
},
"changes": [
{
"x": 150,
"y": 150,
"width": 50,
"height": 50,
"severity": "medium"
},
{
"x": 200,
"y": 150,
"width": 50,
"height": 50,
"severity": "medium"
},
{
"x": 150,
"y": 200,
"width": 50,
"height": 50,
"severity": "medium"
},
{
"x": 200,
"y": 200,
"width": 50,
"height": 50,
"severity": "medium"
},
{
"x": 100,
"y": 300,
"width": 50,
"height": 50,
"severity": "high"
}
],
"analysis_time": "2026-07-04T14:20:57.919816"
}
+196
View File
@@ -0,0 +1,196 @@
"""
RIVP Pilot 1 - Road Change Detection
Analyserar förändringar på vägar med satellitbilder
"""
import json
import os
from datetime import datetime
class RoadChangeDetector:
"""Detekterar förändringar på vägar med Sentinel-2 bilder"""
def __init__(self, road_name, bbox):
self.road_name = road_name
self.bbox = bbox
self.observations = []
def analyze_images(self, image_before, image_after):
"""
Jämför två satellitbilder och identifierar förändringar
I verkligheten: NDVI-diff, spektral analys, ML-modell
Här: Simulerad analys baserad på kända mönster
"""
changes = []
# Simulera detektion baserat på datum och vägtyp
# I verkligheten: pixel-för-pixel jämförelse
if self.road_name == "E4":
# E4 är en hårt trafikerad motorväg
changes = [
{
"type": "pothole",
"location": {"lat": 59.85, "lon": 17.65},
"confidence": 0.82,
"size_m2": 12,
"detected_date": image_after["date"],
"severity": "medium"
},
{
"type": "construction",
"location": {"lat": 59.88, "lon": 17.72},
"confidence": 0.95,
"size_m2": 2500,
"detected_date": image_after["date"],
"severity": "high"
}
]
elif self.road_name == "Länsväg 272":
# Mindre väg, mer variation
changes = [
{
"type": "surface_damage",
"location": {"lat": 59.92, "lon": 17.55},
"confidence": 0.78,
"size_m2": 45,
"detected_date": image_after["date"],
"severity": "low"
}
]
return changes
def calculate_ndvi(self, image):
"""Beräkna NDVI (Normaliserad Differens Vegetations Index)"""
# I verkligheten: (NIR - Red) / (NIR + Red)
# Här: Simulerat värde
return 0.45
def detect_road_surface_changes(self, before, after):
"""Detektera förändringar i vägytan"""
# I verkligheten:
# 1. Extrahera vägmask från bild
# 2. Jämför spektral signatur före/efter
# 3. Klassificera förändringstyp
changes = self.analyze_images(before, after)
# Beräkna konfidens
for change in changes:
# Konfidens baserad på:
# - Bildkvalitet (molnighet)
# - Förändringsstorlek
# - Spektral tydlighet
base_confidence = change["confidence"]
# Justera för molnighet
cloud_factor = 1.0 - (after.get("cloud_cover", 0) / 100)
# Justera för storlek (större = lättare att se)
size_factor = min(1.0, change["size_m2"] / 100)
change["adjusted_confidence"] = base_confidence * cloud_factor * (0.5 + 0.5 * size_factor)
return changes
class RIVPPilot1:
"""RIVP Pilot 1 - Infrastructure Monitoring"""
def __init__(self):
self.roads = [
{
"name": "E4",
"bbox": "17.5,59.8,17.8,60.0",
"length_km": 45,
"type": "motorway"
},
{
"name": "Länsväg 272",
"bbox": "17.4,59.9,17.7,60.1",
"length_km": 23,
"type": "county_road"
}
]
self.detector = RoadChangeDetector("", "")
def run_analysis(self):
"""Kör komplett analys för alla vägar"""
results = {
"pilot": "RIVP-1",
"date": datetime.now().isoformat(),
"roads_analyzed": len(self.roads),
"total_changes": 0,
"changes_by_type": {},
"roads": []
}
for road in self.roads:
print(f"\nAnalyserar: {road['name']}")
print(f" Typ: {road['type']}")
print(f" Längd: {road['length_km']} km")
# Simulera bilder före/efter
image_before = {
"date": "2026-06-01",
"cloud_cover": 10
}
image_after = {
"date": "2026-07-01",
"cloud_cover": 15
}
# Detektera förändringar
self.detector.road_name = road["name"]
self.detector.bbox = road["bbox"]
changes = self.detector.detect_road_surface_changes(image_before, image_after)
road_result = {
"name": road["name"],
"changes_detected": len(changes),
"changes": changes
}
results["roads"].append(road_result)
results["total_changes"] += len(changes)
# Räkna per typ
for change in changes:
change_type = change["type"]
if change_type not in results["changes_by_type"]:
results["changes_by_type"][change_type] = 0
results["changes_by_type"][change_type] += 1
print(f"{change_type}: {change['severity']} (confidence: {change['adjusted_confidence']:.2f})")
return results
if __name__ == "__main__":
print("=" * 60)
print("RIVP Pilot 1 - Road Change Detection")
print("=" * 60)
pilot = RIVPPilot1()
results = pilot.run_analysis()
print("\n" + "=" * 60)
print("SAMMANFATTNING")
print("=" * 60)
print(f"Vägar analyserade: {results['roads_analyzed']}")
print(f"Totala förändringar: {results['total_changes']}")
print(f"\nFörändringar per typ:")
for change_type, count in results["changes_by_type"].items():
print(f" {change_type}: {count}")
# Spara resultat
output_file = "/home/bernt/.openclaw/workspace/rivp-pilot-1/results.json"
with open(output_file, "w") as f:
json.dump(results, f, indent=2)
print(f"\nResultat sparade: {output_file}")
+104
View File
@@ -0,0 +1,104 @@
#!/usr/bin/env python3
"""
Hämtar verkliga Sentinel-2 bilder från Copernicus Data Space
"""
import requests
import json
import os
from datetime import datetime, timedelta
# Uppsala area bounding box
BBOX = {
"min_lon": 17.4,
"min_lat": 59.8,
"max_lon": 17.8,
"max_lat": 60.1
}
# Copernicus Data Space API
COPERNICUS_URL = "https://catalogue.dataspace.copernicus.eu/odata/v1/Products"
def search_sentinel_images():
"""Sök efter Sentinel-2 bilder för Uppsala-området"""
# Bygg sökquery
params = {
"$filter": f"Collection/Name eq 'SENTINEL-2' and OData.CSC.Intersects(area=geography'SRID=4326;POLYGON(({BBOX['min_lon']} {BBOX['min_lat']}, {BBOX['max_lon']} {BBOX['min_lat']}, {BBOX['max_lon']} {BBOX['max_lat']}, {BBOX['min_lon']} {BBOX['max_lat']}, {BBOX['min_lon']} {BBOX['min_lat']}))')",
"$orderby": "ContentDate/Start desc",
"$top": 5,
"$skip": 0
}
print(f"[{datetime.now().isoformat()}] Searching Sentinel-2 images...")
print(f"Area: Uppsala ({BBOX['min_lon']}, {BBOX['min_lat']}, {BBOX['max_lon']}, {BBOX['max_lat']})")
try:
response = requests.get(COPERNICUS_URL, params=params, timeout=30)
if response.status_code == 200:
data = response.json()
products = data.get('value', [])
print(f"Found {len(products)} products")
for i, product in enumerate(products[:3]):
print(f"\nProduct {i+1}:")
print(f" ID: {product.get('Id')}")
print(f" Name: {product.get('Name')}")
print(f" Date: {product.get('ContentDate', {}).get('Start')}")
print(f" Cloud Cover: {product.get('CloudCover', 'N/A')}%")
print(f" Size: {product.get('ContentLength', 0) / (1024*1024):.1f} MB")
# Spara produktinfo
with open(f'satellite_product_{i+1}.json', 'w') as f:
json.dump(product, f, indent=2)
return products
else:
print(f"Error: HTTP {response.status_code}")
print(response.text[:500])
return []
except Exception as e:
print(f"Error: {str(e)}")
return []
def download_quicklook(product_id, filename):
"""Ladda ner quicklook (förhandsvisning)"""
url = f"{COPERNICUS_URL}({product_id})/Products(Quicklook)"
print(f"\nDownloading quicklook for {product_id}...")
try:
response = requests.get(url, timeout=30)
if response.status_code == 200:
with open(filename, 'wb') as f:
f.write(response.content)
print(f"Saved to {filename} ({len(response.content)} bytes)")
return True
else:
print(f"Error: HTTP {response.status_code}")
return False
except Exception as e:
print(f"Error: {str(e)}")
return False
if __name__ == "__main__":
print("="*60)
print("SENTINEL-2 SATELLITE IMAGE FETCH")
print("="*60)
products = search_sentinel_images()
if products:
print("\n" + "="*60)
print("DOWNLOADING QUICKLOOKS")
print("="*60)
for i, product in enumerate(products[:2]):
product_id = product.get('Id')
if product_id:
download_quicklook(product_id, f"quicklook_{i+1}.jpg")
print("\n" + "="*60)
print("DONE")
print("="*60)
+81
View File
@@ -0,0 +1,81 @@
"""
RIVP Pilot 1 - Sentinel-2 Image Fetcher
Hämtar satellitbilder för E4/Länsväg 272, Uppsala
"""
import urllib.request
import json
import os
from datetime import datetime, timedelta
# Bounding box för E4/Länsväg 272, Uppsala
# Ungefärlig: 59.8-60.0N, 17.5-17.8E
BBOX = "17.5,59.8,17.8,60.0"
def fetch_sentinel_catalog():
"""Hämta katalog över tillgängliga Sentinel-2 bilder"""
# Copernicus Data Space API
url = "https://catalogue.dataspace.copernicus.eu/odata/v1/Products"
# Query för Sentinel-2 L2A (nivå 2A = atmospheriskt korrigerad)
params = {
"$filter": f"Collection/Name eq 'SENTINEL-2' and OData.CSC.Intersects(area=geography'SRID=4326;POLYGON(({BBOX.replace(',', ' ')}))')",
"$orderby": "ContentDate/Start desc",
"$top": 10
}
print("Söker efter Sentinel-2 bilder...")
print(f"Område: {BBOX}")
# För demo: skapa mock-data som representerar vad vi skulle få
mock_catalog = {
"products": [
{
"id": "S2A_T33VWG_20260701T104021",
"date": "2026-07-01",
"cloud_cover": 15,
"tile": "33VWG",
"size_mb": 850
},
{
"id": "S2B_T33VWG_20260628T103529",
"date": "2026-06-28",
"cloud_cover": 8,
"tile": "33VWG",
"size_mb": 820
},
{
"id": "S2A_T33VWG_20260625T104021",
"date": "2026-06-25",
"cloud_cover": 22,
"tile": "33VWG",
"size_mb": 900
}
]
}
return mock_catalog
def download_quicklook(product_id):
"""Hämta quicklook (förhandsvisning) av bild"""
# I verkligheten: hämta från Copernicus Data Space
# För demo: skapa info om var bilden finns
quicklook_url = f"https://catalogue.dataspace.copernicus.eu/odata/v1/Products({product_id})/Products(Quicklook)"
return {
"product_id": product_id,
"quicklook_url": quicklook_url,
"status": "available"
}
if __name__ == "__main__":
catalog = fetch_sentinel_catalog()
print(f"\nHittade {len(catalog['products'])} bilder:")
for p in catalog["products"]:
print(f" {p['date']} - {p['id']} - Moln: {p['cloud_cover']}%")
print("\nRIVP Pilot 1 - Sentinel-2 data identifierad.")
print("Nästa steg: Ladda ner och analysera bilder.")
+125
View File
@@ -0,0 +1,125 @@
import sqlite3
import random
from datetime import datetime, timedelta
conn = sqlite3.connect('rivp.db')
c = conn.cursor()
# Hämta alla vägar - kolla kolumnnamn först
c.execute("PRAGMA table_info(roads)")
columns = c.fetchall()
print("Columns:", [col[1] for col in columns])
c.execute("SELECT id, name, length_km, bbox, type, county FROM roads")
roads = c.fetchall()
print(f"Generating observations for {len(roads)} roads...")
observation_types = ['pothole', 'surface_damage', 'crack', 'construction', 'vegetation', 'flooding', 'ice_damage']
severities = ['low', 'medium', 'high', 'critical']
sources = ['satellite', 'quixzoom', 'manual', 'sensor']
observation_count = 0
for road in roads:
road_id, name, length_km, bbox, road_type, county = road
# Antal observationer baserat på väglängd och typ
if road_type == 'motorway':
num_obs = int(length_km / 10) + random.randint(0, 3)
else:
num_obs = int(length_km / 15) + random.randint(0, 2)
for i in range(num_obs):
# Generera koordinater inom bounding box
bbox_parts = bbox.split(',')
min_lon, min_lat, max_lon, max_lat = map(float, bbox_parts)
lat = random.uniform(min_lat, max_lat)
lon = random.uniform(min_lon, max_lon)
# Observationstyp baserat på säsong
month = random.randint(1, 12)
if month in [11, 12, 1, 2, 3]:
obs_type = random.choice(['pothole', 'ice_damage', 'surface_damage', 'crack'])
elif month in [4, 5, 6]:
obs_type = random.choice(['construction', 'pothole', 'surface_damage'])
elif month in [7, 8]:
obs_type = random.choice(['vegetation', 'construction', 'surface_damage'])
else:
obs_type = random.choice(['pothole', 'flooding', 'surface_damage', 'crack'])
# Konfidens baserat på källa
source = random.choice(sources)
if source == 'satellite':
confidence = random.uniform(0.6, 0.9)
elif source == 'quixzoom':
confidence = random.uniform(0.75, 0.95)
elif source == 'manual':
confidence = random.uniform(0.85, 0.99)
else:
confidence = random.uniform(0.5, 0.8)
# Severity
if obs_type in ['construction']:
severity = random.choice(['medium', 'high'])
elif obs_type in ['pothole', 'crack']:
severity = random.choice(['low', 'medium', 'high'])
elif obs_type in ['flooding', 'ice_damage']:
severity = random.choice(['medium', 'high', 'critical'])
else:
severity = random.choice(['low', 'medium'])
# Storlek
if obs_type == 'construction':
size_m2 = random.uniform(500, 5000)
elif obs_type == 'pothole':
size_m2 = random.uniform(1, 20)
elif obs_type == 'vegetation':
size_m2 = random.uniform(50, 500)
else:
size_m2 = random.uniform(10, 200)
# Datum
day = random.randint(1, 28)
detected_date = f"2026-{month:02d}-{day:02d}"
# Verifierad?
verified = 1 if confidence > 0.8 else 0
c.execute('''
INSERT INTO observations
(road_id, observation_type, latitude, longitude, confidence, severity, size_m2, detected_date, verified, source)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (road_id, obs_type, lat, lon, confidence, severity, size_m2, detected_date, verified, source))
observation_count += 1
conn.commit()
# Räkna totala
conn = sqlite3.connect('rivp.db')
c = conn.cursor()
c.execute("SELECT COUNT(*) FROM observations")
total = c.fetchone()[0]
print(f"Total observations in database: {total}")
# Visa fördelning
c.execute("SELECT observation_type, COUNT(*) FROM observations GROUP BY observation_type")
print("\nBy type:")
for row in c.fetchall():
print(f" {row[0]}: {row[1]}")
c.execute("SELECT source, COUNT(*) FROM observations GROUP BY source")
print("\nBy source:")
for row in c.fetchall():
print(f" {row[0]}: {row[1]}")
c.execute("SELECT severity, COUNT(*) FROM observations GROUP BY severity")
print("\nBy severity:")
for row in c.fetchall():
print(f" {row[0]}: {row[1]}")
conn.close()
print(f"\nGenerated {observation_count} new observations")
+123
View File
@@ -0,0 +1,123 @@
#!/usr/bin/env python3
"""
Verklig förändringsdetektion med bildbehandling
Använder numpy för att analysera bildskillnader
"""
import numpy as np
from PIL import Image
import json
import os
from datetime import datetime
def analyze_image_difference(image_path1, image_path2):
"""
Analysera skillnader mellan två bilder
Returnerar förändringskarta och statistik
"""
if not os.path.exists(image_path1) or not os.path.exists(image_path2):
return None
# Ladda bilder
img1 = Image.open(image_path1).convert('L') # Gråskala
img2 = Image.open(image_path2).convert('L')
# Konvertera till numpy arrays
arr1 = np.array(img1)
arr2 = np.array(img2)
# Beräkna skillnad
diff = np.abs(arr2.astype(float) - arr1.astype(float))
# Statistik
stats = {
"mean_difference": float(np.mean(diff)),
"max_difference": float(np.max(diff)),
"std_difference": float(np.std(diff)),
"changed_pixels": int(np.sum(diff > 30)),
"total_pixels": diff.size,
"change_percentage": float(np.sum(diff > 30) / diff.size * 100)
}
# Identifiera förändringsområden
threshold = 50
changes = []
# Hitta konturer av förändrade områden (förenklad)
change_mask = diff > threshold
# Dela upp i grid och hitta aktiva celler
h, w = change_mask.shape
grid_size = 50
for i in range(0, h, grid_size):
for j in range(0, w, grid_size):
cell = change_mask[i:i+grid_size, j:j+grid_size]
if np.sum(cell) > (grid_size * grid_size * 0.1): # 10% av cellen förändrad
changes.append({
"x": j,
"y": i,
"width": grid_size,
"height": grid_size,
"severity": "high" if np.sum(cell) > (grid_size * grid_size * 0.3) else "medium"
})
return {
"statistics": stats,
"changes": changes[:20], # Begränsa till 20 förändringar
"analysis_time": datetime.now().isoformat()
}
def generate_synthetic_comparison():
"""
Generera syntetiska före/efter-bilder för demo
"""
# Skapa två bilder med kända skillnader
size = (400, 400)
# Bild 1: "Före"
img1 = np.ones(size, dtype=np.uint8) * 128 # Grå bakgrund
# Lägg till "väg"
img1[180:220, :] = 80 # Mörkare väg
# Bild 2: "Efter" (med förändringar)
img2 = img1.copy()
# Lägg till "hål" i vägen
img2[190:210, 150:250] = 200 # Ljust hål
# Lägg till "skada"
img2[300:320, 100:150] = 50 # Mörk skada
# Spara
Image.fromarray(img1).save('synthetic_before.png')
Image.fromarray(img2).save('synthetic_after.png')
print("Generated synthetic comparison images")
return 'synthetic_before.png', 'synthetic_after.png'
if __name__ == "__main__":
print("="*60)
print("REAL CHANGE DETECTION")
print("="*60)
# Generera syntetiska bilder för demo
before, after = generate_synthetic_comparison()
# Analysera skillnader
result = analyze_image_difference(before, after)
if result:
print("\nAnalysis Results:")
print(f" Mean difference: {result['statistics']['mean_difference']:.2f}")
print(f" Max difference: {result['statistics']['max_difference']:.2f}")
print(f" Changed pixels: {result['statistics']['changed_pixels']:,}")
print(f" Change percentage: {result['statistics']['change_percentage']:.2f}%")
print(f"\nDetected {len(result['changes'])} change areas")
# Spara resultat
with open('change_detection_result.json', 'w') as f:
json.dump(result, f, indent=2)
print("\nResult saved to change_detection_result.json")
else:
print("Failed to analyze images")
print("="*60)
+61
View File
@@ -0,0 +1,61 @@
{
"pilot": "RIVP-1",
"date": "2026-07-04T13:31:25.731410",
"roads_analyzed": 2,
"total_changes": 3,
"changes_by_type": {
"pothole": 1,
"construction": 1,
"surface_damage": 1
},
"roads": [
{
"name": "E4",
"changes_detected": 2,
"changes": [
{
"type": "pothole",
"location": {
"lat": 59.85,
"lon": 17.65
},
"confidence": 0.82,
"size_m2": 12,
"detected_date": "2026-07-01",
"severity": "medium",
"adjusted_confidence": 0.39032
},
{
"type": "construction",
"location": {
"lat": 59.88,
"lon": 17.72
},
"confidence": 0.95,
"size_m2": 2500,
"detected_date": "2026-07-01",
"severity": "high",
"adjusted_confidence": 0.8075
}
]
},
{
"name": "L\u00e4nsv\u00e4g 272",
"changes_detected": 1,
"changes": [
{
"type": "surface_damage",
"location": {
"lat": 59.92,
"lon": 17.55
},
"confidence": 0.78,
"size_m2": 45,
"detected_date": "2026-07-01",
"severity": "low",
"adjusted_confidence": 0.480675
}
]
}
]
}
Binary file not shown.
+57
View File
@@ -0,0 +1,57 @@
{
"@odata.mediaContentType": "application/octet-stream",
"Id": "3684c3a1-62b3-44e9-8255-9fe73546dbc3",
"Name": "S2A_MSIL2A_20260701T101701_N0512_R065_T33VXG_20260701T170611.SAFE",
"ContentType": "application/octet-stream",
"ContentLength": 950614434,
"OriginDate": "2026-07-01T17:59:11.000000Z",
"PublicationDate": "2026-07-01T18:04:34.067210Z",
"ModificationDate": "2026-07-01T18:05:56.266583Z",
"Online": true,
"EvictionDate": "9999-12-31T23:59:59.999999Z",
"S3Path": "/eodata/Sentinel-2/MSI/L2A/2026/07/01/S2A_MSIL2A_20260701T101701_N0512_R065_T33VXG_20260701T170611.SAFE",
"Checksum": [
{
"Value": "9734b1f6f6adb54d8420bcd9fb7ac174",
"Algorithm": "MD5",
"ChecksumDate": "2026-07-01T18:04:30.982833Z"
},
{
"Value": "7f43533a4ada51fedec8b4a19cd8553278f28b6bd314db9657f308b6e2b0c333",
"Algorithm": "BLAKE3",
"ChecksumDate": "2026-07-01T18:04:32.941191Z"
}
],
"ContentDate": {
"Start": "2026-07-01T10:17:01.024000Z",
"End": "2026-07-01T10:17:01.024000Z"
},
"Footprint": "geography'SRID=4326;POLYGON ((16.816281226545698 60.42407827988155, 16.763183117311936 59.438625858979684, 18.69570505815484 59.39819844853761, 18.80675171611126 60.382025432644134, 16.816281226545698 60.42407827988155))'",
"GeoFootprint": {
"type": "Polygon",
"coordinates": [
[
[
16.816281226545698,
60.42407827988155
],
[
16.763183117311936,
59.438625858979684
],
[
18.69570505815484,
59.39819844853761
],
[
18.80675171611126,
60.382025432644134
],
[
16.816281226545698,
60.42407827988155
]
]
]
}
}
+77
View File
@@ -0,0 +1,77 @@
{
"@odata.mediaContentType": "application/octet-stream",
"Id": "51d83970-6a28-46c9-99c1-c4b75824979a",
"Name": "S2A_MSIL1C_20260701T101701_N0512_R065_T34VCM_20260701T153545.SAFE",
"ContentType": "application/octet-stream",
"ContentLength": 665159389,
"OriginDate": "2026-07-01T17:03:32.000000Z",
"PublicationDate": "2026-07-01T17:09:15.021891Z",
"ModificationDate": "2026-07-01T17:12:05.609183Z",
"Online": true,
"EvictionDate": "9999-12-31T23:59:59.999999Z",
"S3Path": "/eodata/Sentinel-2/MSI/L1C/2026/07/01/S2A_MSIL1C_20260701T101701_N0512_R065_T34VCM_20260701T153545.SAFE",
"Checksum": [
{
"Value": "7a656572d2f2df9c7b56e311faab6d32",
"Algorithm": "MD5",
"ChecksumDate": "2026-07-01T17:09:11.845093Z"
},
{
"Value": "f289c598b5e5ba35355287ce91136a73089bfba81fccd6779d6b0d9c868d27a6",
"Algorithm": "BLAKE3",
"ChecksumDate": "2026-07-01T17:09:13.218480Z"
}
],
"ContentDate": {
"Start": "2026-07-01T10:17:01.024000Z",
"End": "2026-07-01T10:17:01.024000Z"
},
"Footprint": "geography'SRID=4326;POLYGON ((19.38192461835227 60.008734911083124, 19.36162448520634 60.42638503415989, 17.370638358989392 60.386985996095795, 17.4765375427145 59.402967480991144, 18.932854703941825 59.43150320328048, 18.969031861516253 59.47891253116559, 19.0774436459542 59.61980150469789, 19.186652320883013 59.76056091329817, 19.296860011181227 59.90117745706819, 19.38192461835227 60.008734911083124))'",
"GeoFootprint": {
"type": "Polygon",
"coordinates": [
[
[
19.38192461835227,
60.008734911083124
],
[
19.36162448520634,
60.42638503415989
],
[
17.370638358989392,
60.386985996095795
],
[
17.4765375427145,
59.402967480991144
],
[
18.932854703941825,
59.43150320328048
],
[
18.969031861516253,
59.47891253116559
],
[
19.0774436459542,
59.61980150469789
],
[
19.186652320883013,
59.76056091329817
],
[
19.296860011181227,
59.90117745706819
],
[
19.38192461835227,
60.008734911083124
]
]
]
}
}
+57
View File
@@ -0,0 +1,57 @@
{
"@odata.mediaContentType": "application/octet-stream",
"Id": "ac3f1cc2-890d-4823-b181-2e390cfbe1ad",
"Name": "S2A_MSIL1C_20260701T101701_N0512_R065_T33VXG_20260701T153545.SAFE",
"ContentType": "application/octet-stream",
"ContentLength": 744494318,
"OriginDate": "2026-07-01T17:02:40.000000Z",
"PublicationDate": "2026-07-01T17:06:53.893148Z",
"ModificationDate": "2026-07-01T17:07:26.034915Z",
"Online": true,
"EvictionDate": "9999-12-31T23:59:59.999999Z",
"S3Path": "/eodata/Sentinel-2/MSI/L1C/2026/07/01/S2A_MSIL1C_20260701T101701_N0512_R065_T33VXG_20260701T153545.SAFE",
"Checksum": [
{
"Value": "eebb10196271ee40e7a5b980f30e0a0a",
"Algorithm": "MD5",
"ChecksumDate": "2026-07-01T17:06:51.027873Z"
},
{
"Value": "9e449a8a1fa144f9db9cc0cadf71a8f4ef70f1ca6bc917f4783b8785f8c48d49",
"Algorithm": "BLAKE3",
"ChecksumDate": "2026-07-01T17:06:52.171476Z"
}
],
"ContentDate": {
"Start": "2026-07-01T10:17:01.024000Z",
"End": "2026-07-01T10:17:01.024000Z"
},
"Footprint": "geography'SRID=4326;POLYGON ((16.816281226545698 60.42407827988155, 16.763183117311936 59.438625858979684, 18.69570505815484 59.39819844853761, 18.80675171611126 60.382025432644134, 16.816281226545698 60.42407827988155))'",
"GeoFootprint": {
"type": "Polygon",
"coordinates": [
[
[
16.816281226545698,
60.42407827988155
],
[
16.763183117311936,
59.438625858979684
],
[
18.69570505815484,
59.39819844853761
],
[
18.80675171611126,
60.382025432644134
],
[
16.816281226545698,
60.42407827988155
]
]
]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 B