Vertdure commited on
Commit
5abcc84
‱
1 Parent(s): c9e0eba

Update pages/12_đŸŒČ_VertXtractor.py

Browse files
Files changed (1) hide show
  1. pages/12_đŸŒČ_VertXtractor.py +112 -90
pages/12_đŸŒČ_VertXtractor.py CHANGED
@@ -6,22 +6,14 @@ from folium.plugins import Draw
6
  import requests
7
  from shapely.geometry import box
8
  import json
 
 
 
 
9
 
10
  st.set_page_config(layout="wide", page_title="Extracteur de donnĂ©es gĂ©ospatiales")
11
 
12
- def get_swisstopo_collections():
13
- url = "https://data.geo.admin.ch/api/stac/v0.9/collections"
14
- response = requests.get(url)
15
- if response.status_code == 200:
16
- collections = response.json()['collections']
17
- return {c['title']: {"id": c['id'], "source": "swisstopo", "type": c.get('type', 'unknown')} for c in collections}
18
- else:
19
- st.error("Impossible de récupérer les collections Swisstopo")
20
- return {}
21
-
22
- SWISSTOPO_ALL = get_swisstopo_collections()
23
-
24
- SWISSTOPO_SELECTED = {
25
  "SWISSIMAGE 10 cm": {"id": "ch.swisstopo.swissimage-dop10", "source": "swisstopo", "type": "image"},
26
  "Carte nationale 1:25'000": {"id": "ch.swisstopo.pixelkarte-farbe-pk25.noscale", "source": "swisstopo", "type": "image"},
27
  "MNT": {"id": "ch.swisstopo.swissalti3d", "source": "swisstopo", "type": "raster"},
@@ -50,64 +42,114 @@ def create_geojson_from_box(bbox):
50
  return json.loads(gdf.to_json()), json.loads(gdf.to_crs("EPSG:2056").to_json())
51
 
52
  @st.cache_data
53
- def get_download_url(bbox, layer_info):
54
- urls = {"swisstopo": None, "esri": None}
55
-
56
- # Swisstopo
57
- if layer_info["source"] == "swisstopo":
58
- api_url = f"https://data.geo.admin.ch/api/stac/v0.9/collections/{layer_info['id']}/items"
59
- params = {"bbox": ",".join(map(str, bbox)), "limit": 1}
60
  response = requests.get(api_url, params=params)
 
61
  data = response.json()
62
- if 'features' in data and data['features']:
63
  feature = data['features'][0]
64
- assets = feature.get('assets', {})
65
- if layer_info['id'] == 'ch.swisstopo.swissimage-dop10':
66
- data_key = 'rgb' if 'rgb' in assets else 'data' if 'data' in assets else None
67
- else:
68
- data_key = 'data' if 'data' in assets else next(iter(assets)) if assets else None
69
-
70
- if data_key and data_key in assets:
71
- urls["swisstopo"] = assets[data_key].get('href')
72
-
73
- # ESRI
74
- if layer_info["id"] in [layer["id"] for layer in ESRI_LAYERS.values()]:
75
- service_url = f"https://services.arcgisonline.com/arcgis/rest/services/{layer_info['id']}/MapServer/export"
76
- params = {
77
- "bbox": f"{bbox[0]},{bbox[1]},{bbox[2]},{bbox[3]}",
78
- "bboxSR": 4326,
79
- "size": "1000,1000",
80
- "format": "png",
81
- "f": "html",
82
- "imageSR": 4326,
83
- "transparent": "true"
84
- }
85
- urls["esri"] = f"{service_url}?{'&'.join([f'{k}={v}' for k, v in params.items()])}"
86
-
87
- return urls
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
  def main():
90
- st.title("Extracteur de données géospatiales")
91
 
92
- col1, col2 = st.columns([1, 2])
 
 
 
93
 
94
  with col1:
95
- st.subheader("1. SĂ©lectionner les couches")
96
- source = st.radio("Source des données", ["Swisstopo (Sélection)", "Swisstopo (Toutes)", "ESRI"])
97
 
98
- if source == "Swisstopo (SĂ©lection)":
99
- layers = SWISSTOPO_SELECTED
100
- elif source == "Swisstopo (Toutes)":
101
- layers = SWISSTOPO_ALL
102
- else:
103
- layers = ESRI_LAYERS
104
-
105
- selected_layers = st.multiselect("Couches Ă  extraire", list(layers.keys()))
 
 
106
 
107
- st.subheader("2. DĂ©finir la zone d'intĂ©rĂȘt")
 
108
  method = st.radio("MĂ©thode", ["Dessiner", "GeoJSON"], horizontal=True)
109
-
110
- if method == "GeoJSON":
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  uploaded_file = st.file_uploader("GeoJSON", type="geojson")
112
  if uploaded_file:
113
  gdf = gpd.read_file(uploaded_file)
@@ -115,40 +157,20 @@ def main():
115
  st.session_state['geojson_swiss'] = json.loads(gdf.to_crs(2056).to_json())
116
  st.success("GeoJSON chargĂ©!")
117
 
118
- st.subheader("3. Télécharger les données")
119
- if st.button("Obtenir les liens de téléchargement"):
120
  if 'geojson_wgs84' not in st.session_state or 'geojson_swiss' not in st.session_state:
121
  st.error("DĂ©finissez d'abord une zone d'intĂ©rĂȘt.")
122
- elif not selected_layers:
123
  st.error("SĂ©lectionnez au moins une couche Ă  extraire.")
124
  else:
125
- for layer_name in selected_layers:
126
- layer_info = layers[layer_name]
127
- bbox = gpd.GeoDataFrame.from_features(st.session_state['geojson_swiss' if layer_info["source"] == "swisstopo" else 'geojson_wgs84']).total_bounds
128
- st.write(f"Traitement de la couche : {layer_name}")
129
- st.write(f"Bbox : {bbox}")
130
- try:
131
- download_urls = get_download_url(bbox, layer_info)
132
- if download_urls["swisstopo"]:
133
- st.markdown(f"[Télécharger {layer_name} (Swisstopo)]({download_urls['swisstopo']})")
134
- if download_urls["esri"]:
135
- st.markdown(f"[Télécharger {layer_name} (ESRI)]({download_urls['esri']})")
136
- if not download_urls["swisstopo"] and not download_urls["esri"]:
137
- st.warning(f"Aucun lien de téléchargement disponible pour {layer_name}")
138
- except Exception as e:
139
- st.error(f"Erreur lors de la récupération du lien pour {layer_name}: {str(e)}")
140
-
141
- with col2:
142
- if method == "Dessiner":
143
- map_data = draw_box_on_map()
144
- if map_data['last_active_drawing']:
145
- coords = map_data['last_active_drawing']['geometry']['coordinates'][0]
146
- bbox = box(min(c[0] for c in coords), min(c[1] for c in coords),
147
- max(c[0] for c in coords), max(c[1] for c in coords))
148
- st.session_state['geojson_wgs84'], st.session_state['geojson_swiss'] = create_geojson_from_box(bbox)
149
- st.success("Zone sélectionnée!")
150
-
151
- st.sidebar.markdown("## À propos\nExtracteur de donnĂ©es gĂ©ospatiales Swisstopo et ESRI.\nDĂ©veloppĂ© par Vertdure")
152
 
153
  if __name__ == "__main__":
154
  main()
 
6
  import requests
7
  from shapely.geometry import box
8
  import json
9
+ import io
10
+ import rasterio
11
+ from rasterio.io import MemoryFile
12
+ import numpy as np
13
 
14
  st.set_page_config(layout="wide", page_title="Extracteur de donnĂ©es gĂ©ospatiales")
15
 
16
+ SWISSTOPO_LAYERS = {
 
 
 
 
 
 
 
 
 
 
 
 
17
  "SWISSIMAGE 10 cm": {"id": "ch.swisstopo.swissimage-dop10", "source": "swisstopo", "type": "image"},
18
  "Carte nationale 1:25'000": {"id": "ch.swisstopo.pixelkarte-farbe-pk25.noscale", "source": "swisstopo", "type": "image"},
19
  "MNT": {"id": "ch.swisstopo.swissalti3d", "source": "swisstopo", "type": "raster"},
 
42
  return json.loads(gdf.to_json()), json.loads(gdf.to_crs("EPSG:2056").to_json())
43
 
44
  @st.cache_data
45
+ def extract_swisstopo_data(bbox, layer_id, layer_type):
46
+ api_url = f"https://data.geo.admin.ch/api/stac/v0.9/collections/{layer_id}/items"
47
+ params = {"bbox": ",".join(map(str, bbox)), "limit": 1}
48
+ try:
 
 
 
49
  response = requests.get(api_url, params=params)
50
+ response.raise_for_status()
51
  data = response.json()
52
+ if data['features']:
53
  feature = data['features'][0]
54
+ asset_keys = feature['assets'].keys()
55
+ data_key = 'rgb' if 'rgb' in asset_keys else 'data' if 'data' in asset_keys else next(iter(asset_keys))
56
+ data_url = feature['assets'][data_key]['href']
57
+ return requests.get(data_url).content
58
+ except requests.RequestException as e:
59
+ st.error(f"Erreur Swisstopo: {str(e)}")
60
+ return None
61
+
62
+ @st.cache_data
63
+ def extract_esri_data(bbox, layer_id, layer_type):
64
+ service_url = f"https://services.arcgisonline.com/arcgis/rest/services/{layer_id}/MapServer/export"
65
+ params = {
66
+ "bbox": f"{bbox[0]},{bbox[1]},{bbox[2]},{bbox[3]}",
67
+ "bboxSR": 4326,
68
+ "size": "1000,1000",
69
+ "format": "tiff",
70
+ "f": "image"
71
+ }
72
+ try:
73
+ response = requests.get(service_url, params=params)
74
+ response.raise_for_status()
75
+ return response.content
76
+ except requests.RequestException as e:
77
+ st.error(f"Erreur ESRI: {str(e)}")
78
+ return None
79
+
80
+ def process_and_display_data(data, layer_name, layer_type):
81
+ if data is None:
82
+ st.warning(f"Pas de données pour {layer_name}")
83
+ return
84
+ try:
85
+ with MemoryFile(data) as memfile:
86
+ with memfile.open() as src:
87
+ image = src.read()
88
+ if image.shape[0] == 3:
89
+ image = np.transpose(image, (1, 2, 0))
90
+ elif image.shape[0] == 1:
91
+ image = image[0]
92
+
93
+ st.image(image, caption=layer_name, use_column_width=True)
94
+
95
+ output = io.BytesIO()
96
+ with MemoryFile(output) as memfile:
97
+ with memfile.open(**src.profile) as dst:
98
+ dst.write(src.read())
99
+
100
+ st.download_button(
101
+ label=f"Télécharger {layer_name} (GeoTIFF)",
102
+ data=output.getvalue(),
103
+ file_name=f"{layer_name.lower().replace(' ', '_')}.tif",
104
+ mime="image/tiff"
105
+ )
106
+ except Exception as e:
107
+ st.error(f"Erreur de traitement pour {layer_name}: {str(e)}")
108
 
109
  def main():
110
+ st.title("Extracteur de données Swisstopo et ESRI")
111
 
112
+ if 'selected_layers' not in st.session_state:
113
+ st.session_state.selected_layers = set()
114
+
115
+ col1, col2 = st.columns([1, 3])
116
 
117
  with col1:
118
+ st.subheader("SĂ©lection des couches")
119
+ source = st.radio("Source des données", ["Swisstopo", "ESRI"])
120
 
121
+ layers = SWISSTOPO_LAYERS if source == "Swisstopo" else ESRI_LAYERS
122
+
123
+ for layer_name in layers:
124
+ if st.checkbox(layer_name, value=layer_name in st.session_state.selected_layers):
125
+ st.session_state.selected_layers.add(layer_name)
126
+ else:
127
+ st.session_state.selected_layers.discard(layer_name)
128
+
129
+ st.markdown("---")
130
+ st.markdown("## À propos\nExtracteur de donnĂ©es gĂ©ospatiales Swisstopo et ESRI.\nDĂ©veloppĂ© par Vertdure")
131
 
132
+ with col2:
133
+ st.subheader("1. DĂ©finir la zone d'intĂ©rĂȘt")
134
  method = st.radio("MĂ©thode", ["Dessiner", "GeoJSON"], horizontal=True)
135
+ if method == "Dessiner":
136
+ if 'bbox' not in st.session_state:
137
+ map_data = draw_box_on_map()
138
+ if map_data['last_active_drawing']:
139
+ coords = map_data['last_active_drawing']['geometry']['coordinates'][0]
140
+ bbox = box(min(c[0] for c in coords), min(c[1] for c in coords),
141
+ max(c[0] for c in coords), max(c[1] for c in coords))
142
+ st.session_state['bbox'] = bbox
143
+ st.session_state['geojson_wgs84'], st.session_state['geojson_swiss'] = create_geojson_from_box(bbox)
144
+ st.success("Zone sélectionnée!")
145
+ else:
146
+ st.success("Zone déjà sélectionnée. Cliquez sur 'Effacer la zone' pour redessiner.")
147
+ if st.button("Effacer la zone"):
148
+ del st.session_state['bbox']
149
+ del st.session_state['geojson_wgs84']
150
+ del st.session_state['geojson_swiss']
151
+ st.experimental_rerun()
152
+ else:
153
  uploaded_file = st.file_uploader("GeoJSON", type="geojson")
154
  if uploaded_file:
155
  gdf = gpd.read_file(uploaded_file)
 
157
  st.session_state['geojson_swiss'] = json.loads(gdf.to_crs(2056).to_json())
158
  st.success("GeoJSON chargĂ©!")
159
 
160
+ if st.button("Extraire les données"):
 
161
  if 'geojson_wgs84' not in st.session_state or 'geojson_swiss' not in st.session_state:
162
  st.error("DĂ©finissez d'abord une zone d'intĂ©rĂȘt.")
163
+ elif not st.session_state.selected_layers:
164
  st.error("SĂ©lectionnez au moins une couche Ă  extraire.")
165
  else:
166
+ with st.spinner("Extraction des données en cours..."):
167
+ for layer_name in st.session_state.selected_layers:
168
+ layer_info = SWISSTOPO_LAYERS.get(layer_name) or ESRI_LAYERS.get(layer_name)
169
+ bbox = gpd.GeoDataFrame.from_features(st.session_state['geojson_swiss' if layer_info["source"] == "swisstopo" else 'geojson_wgs84']).total_bounds
170
+ st.info(f"Traitement de la couche : {layer_name}")
171
+ data = extract_swisstopo_data(bbox, layer_info["id"], layer_info["type"]) if layer_info["source"] == "swisstopo" else extract_esri_data(bbox, layer_info["id"], layer_info["type"])
172
+ process_and_display_data(data, layer_name, layer_info["type"])
173
+ st.success("Extraction terminée !")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
  if __name__ == "__main__":
176
  main()