tunned-geobr 0.2.2__py3-none-any.whl → 0.2.4__py3-none-any.whl
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.
- tunned_geobr/__init__.py +59 -1
- tunned_geobr/list_geobr.py +74 -3
- tunned_geobr/read_ama_anemometric_towers.py +119 -0
- tunned_geobr/read_areas_under_contract.py +129 -0
- tunned_geobr/read_biodiesel_plants.py +128 -0
- tunned_geobr/read_biomethane_plants.py +128 -0
- tunned_geobr/read_compression_stations.py +128 -0
- tunned_geobr/read_drainage_ducts.py +128 -0
- tunned_geobr/read_etanol_plants.py +128 -0
- tunned_geobr/read_existent_biomass_ute.py +128 -0
- tunned_geobr/read_existent_cgh.py +168 -0
- tunned_geobr/read_existent_eolic.py +165 -0
- tunned_geobr/read_existent_fossile_ute.py +128 -0
- tunned_geobr/read_existent_nuclear_ute.py +128 -0
- tunned_geobr/read_existent_pch.py +168 -0
- tunned_geobr/read_existent_solar.py +165 -0
- tunned_geobr/read_existent_substations.py +128 -0
- tunned_geobr/read_existent_transmission_lines.py +128 -0
- tunned_geobr/read_existent_uhe.py +168 -0
- tunned_geobr/read_exploration_production_environment.py +119 -0
- tunned_geobr/read_federal_union_areas.py +129 -0
- tunned_geobr/read_fuel_bases.py +128 -0
- tunned_geobr/read_gas_distribution_pipelines.py +128 -0
- tunned_geobr/read_gas_transport_pipelines.py +128 -0
- tunned_geobr/read_glp_bases.py +128 -0
- tunned_geobr/read_gnl_terminals.py +128 -0
- tunned_geobr/read_hydroelectric_feasibility_studies.py +119 -0
- tunned_geobr/read_hydroelectric_inventory_aai_studies.py +119 -0
- tunned_geobr/read_isolated_systems.py +128 -0
- tunned_geobr/read_natural_gas_delivery_points.py +128 -0
- tunned_geobr/read_natural_gas_processing_hub.py +128 -0
- tunned_geobr/read_og_basement.py +119 -0
- tunned_geobr/read_og_effective_geographic_basin.py +129 -0
- tunned_geobr/read_og_ipa_direct_evidence.py +119 -0
- tunned_geobr/read_og_ipa_exploratory_activity.py +119 -0
- tunned_geobr/read_og_ipa_exploratory_intensity.py +129 -0
- tunned_geobr/read_og_ipa_need_for_knowledge.py +119 -0
- tunned_geobr/read_og_ipa_prospectiveness.py +119 -0
- tunned_geobr/read_og_ipa_supply_infrastructure.py +119 -0
- tunned_geobr/read_og_legal_pre_salt_polygon.py +119 -0
- tunned_geobr/read_og_predominant_fluid_type.py +129 -0
- tunned_geobr/read_og_probabilistic_effective_basin.py +129 -0
- tunned_geobr/read_og_total_ipa.py +129 -0
- tunned_geobr/read_og_unconventional_resources.py +129 -0
- tunned_geobr/read_oil_and_derivatives_terminal.py +128 -0
- tunned_geobr/read_pan_strategic_areas 2.py +71 -0
- tunned_geobr/read_pio_ducts.py +128 -0
- tunned_geobr/read_pio_terminals.py +128 -0
- tunned_geobr/read_planned_biomass_ute.py +166 -0
- tunned_geobr/read_planned_cgh.py +166 -0
- tunned_geobr/read_planned_eolic.py +165 -0
- tunned_geobr/read_planned_fossile_ute.py +166 -0
- tunned_geobr/read_planned_nuclear_ute.py +165 -0
- tunned_geobr/read_planned_pch.py +166 -0
- tunned_geobr/read_planned_solar.py +165 -0
- tunned_geobr/read_planned_substations.py +164 -0
- tunned_geobr/read_planned_transmission_lines.py +165 -0
- tunned_geobr/read_planned_uhe.py +166 -0
- tunned_geobr/read_processing_facilities.py +128 -0
- tunned_geobr/read_sedimentary_basins.py +119 -0
- tunned_geobr/read_subsystem_interconnected.py +163 -0
- {tunned_geobr-0.2.2.dist-info → tunned_geobr-0.2.4.dist-info}/METADATA +1 -1
- {tunned_geobr-0.2.2.dist-info → tunned_geobr-0.2.4.dist-info}/RECORD +66 -8
- tunned_geobr/constants.py +0 -13
- {tunned_geobr-0.2.2.dist-info → tunned_geobr-0.2.4.dist-info}/WHEEL +0 -0
- {tunned_geobr-0.2.2.dist-info → tunned_geobr-0.2.4.dist-info}/entry_points.txt +0 -0
- {tunned_geobr-0.2.2.dist-info → tunned_geobr-0.2.4.dist-info}/licenses/LICENSE.txt +0 -0
@@ -0,0 +1,166 @@
|
|
1
|
+
import geopandas as gpd
|
2
|
+
import os
|
3
|
+
import tempfile
|
4
|
+
import urllib.parse
|
5
|
+
import requests
|
6
|
+
import shutil
|
7
|
+
from zipfile import ZipFile
|
8
|
+
from pathlib import Path
|
9
|
+
from io import BytesIO
|
10
|
+
import warnings
|
11
|
+
import json
|
12
|
+
|
13
|
+
def read_planned_biomass_ute(simplified=False, verbose=False):
|
14
|
+
"""Download Planned Biomass Thermoelectric Power Plants data from EPE.
|
15
|
+
|
16
|
+
This function downloads and processes planned biomass thermoelectric power plants data from EPE
|
17
|
+
(Energy Research Company). The data includes information about planned biomass thermoelectric
|
18
|
+
power generation projects across Brazil.
|
19
|
+
Original source: EPE (Empresa de Pesquisa Energética)
|
20
|
+
|
21
|
+
Parameters
|
22
|
+
----------
|
23
|
+
simplified : boolean, by default False
|
24
|
+
If True, returns a simplified version of the dataset with fewer columns
|
25
|
+
verbose : boolean, by default False
|
26
|
+
If True, prints detailed information about the download process
|
27
|
+
|
28
|
+
Returns
|
29
|
+
-------
|
30
|
+
gpd.GeoDataFrame
|
31
|
+
Geodataframe with planned biomass thermoelectric power plants data
|
32
|
+
|
33
|
+
Example
|
34
|
+
-------
|
35
|
+
>>> from tunned_geobr import read_planned_biomass_ute
|
36
|
+
|
37
|
+
# Read planned biomass thermoelectric power plants data
|
38
|
+
>>> planned_biomass_ute = read_planned_biomass_ute()
|
39
|
+
"""
|
40
|
+
|
41
|
+
# URL for the EPE geoserver
|
42
|
+
url = r"https://gisepeprd2.epe.gov.br/arcgis/rest/services/Download_Dados_Webmap_EPE/GPServer/Extract%20Data%20Task/execute?f=json&env%3AoutSR=102100&Layers_to_Clip=%5B%22UTE%20Biomassa%20-%20Expans%C3%A3o%20Planejada%22%5D&Area_of_Interest=%7B%22geometryType%22%3A%22esriGeometryPolygon%22%2C%22features%22%3A%5B%7B%22geometry%22%3A%7B%22rings%22%3A%5B%5B%5B-8655251.47456396%2C-4787514.465591563%5D%2C%5B-8655251.47456396%2C1229608.401015912%5D%2C%5B-3508899.2341809804%2C1229608.401015912%5D%2C%5B-3508899.2341809804%2C-4787514.465591563%5D%2C%5B-8655251.47456396%2C-4787514.465591563%5D%5D%5D%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%7D%7D%7D%5D%2C%22sr%22%3A%7B%22wkid%22%3A102100%7D%7D&Feature_Format=Shapefile%20-%20SHP%20-%20.shp&Raster_Format=Tagged%20Image%20File%20Format%20-%20TIFF%20-%20.tif"
|
43
|
+
|
44
|
+
try:
|
45
|
+
# Disable SSL verification warning
|
46
|
+
warnings.filterwarnings('ignore', message='Unverified HTTPS request')
|
47
|
+
|
48
|
+
if verbose:
|
49
|
+
print("Requesting data from EPE server...")
|
50
|
+
|
51
|
+
response = requests.get(url, timeout=60, verify=False)
|
52
|
+
if not response.ok:
|
53
|
+
raise Exception(f"Error getting JSON response: {response.status_code}")
|
54
|
+
|
55
|
+
json_response = response.json()
|
56
|
+
|
57
|
+
if verbose:
|
58
|
+
print(f"JSON response received: {json.dumps(json_response, indent=2)[:500]}...")
|
59
|
+
|
60
|
+
if 'results' not in json_response or len(json_response['results']) == 0:
|
61
|
+
raise Exception("Invalid JSON response structure")
|
62
|
+
|
63
|
+
if 'value' not in json_response['results'][0] or 'url' not in json_response['results'][0]['value']:
|
64
|
+
raise Exception("URL not found in JSON response")
|
65
|
+
|
66
|
+
file_url = json_response['results'][0]['value']['url']
|
67
|
+
|
68
|
+
if verbose:
|
69
|
+
print(f"Downloading file from: {file_url}")
|
70
|
+
|
71
|
+
file_response = requests.get(file_url, stream=True, timeout=60, verify=False)
|
72
|
+
if not file_response.ok:
|
73
|
+
raise Exception(f"Error downloading file: {file_response.status_code}")
|
74
|
+
|
75
|
+
# Check if content is actually a zip file
|
76
|
+
content = file_response.content
|
77
|
+
if len(content) < 100:
|
78
|
+
if verbose:
|
79
|
+
print(f"Warning: Downloaded content is very small ({len(content)} bytes)")
|
80
|
+
print(f"Content preview: {content[:100]}")
|
81
|
+
|
82
|
+
# Create a temporary directory to extract the files
|
83
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
84
|
+
if verbose:
|
85
|
+
print(f"Extracting files to temporary directory: {temp_dir}")
|
86
|
+
|
87
|
+
try:
|
88
|
+
# Extract the zip file
|
89
|
+
with ZipFile(BytesIO(content)) as zip_ref:
|
90
|
+
zip_ref.extractall(temp_dir)
|
91
|
+
|
92
|
+
if verbose:
|
93
|
+
print(f"Files in zip: {zip_ref.namelist()}")
|
94
|
+
except Exception as zip_error:
|
95
|
+
if verbose:
|
96
|
+
print(f"Error extracting zip: {str(zip_error)}")
|
97
|
+
print(f"Saving content to debug.zip for inspection")
|
98
|
+
with open("debug.zip", "wb") as f:
|
99
|
+
f.write(content)
|
100
|
+
raise Exception(f"Failed to extract zip file: {str(zip_error)}")
|
101
|
+
|
102
|
+
# Find the shapefile
|
103
|
+
all_files = os.listdir(temp_dir)
|
104
|
+
if verbose:
|
105
|
+
print(f"Files in temp directory: {all_files}")
|
106
|
+
|
107
|
+
shp_files = [f for f in all_files if f.endswith('.shp')]
|
108
|
+
if not shp_files:
|
109
|
+
# Try looking in subdirectories
|
110
|
+
for root, dirs, files in os.walk(temp_dir):
|
111
|
+
shp_files.extend([os.path.join(root, f) for f in files if f.endswith('.shp')])
|
112
|
+
|
113
|
+
if not shp_files:
|
114
|
+
raise Exception("No shapefile found in the downloaded data")
|
115
|
+
|
116
|
+
# Read the shapefile
|
117
|
+
shp_path = shp_files[0] if os.path.isabs(shp_files[0]) else os.path.join(temp_dir, shp_files[0])
|
118
|
+
if verbose:
|
119
|
+
print(f"Reading shapefile: {shp_path}")
|
120
|
+
|
121
|
+
gdf = gpd.read_file(shp_path)
|
122
|
+
|
123
|
+
# Convert to SIRGAS 2000 (EPSG:4674)
|
124
|
+
gdf = gdf.to_crs(4674)
|
125
|
+
|
126
|
+
if verbose:
|
127
|
+
print(f"Data loaded successfully with {len(gdf)} records")
|
128
|
+
print(f"Columns: {gdf.columns.tolist()}")
|
129
|
+
|
130
|
+
if simplified:
|
131
|
+
# Keep only the most relevant columns
|
132
|
+
columns_to_keep = [
|
133
|
+
'geometry',
|
134
|
+
'nome', # Power plant name
|
135
|
+
'potencia', # Capacity in MW
|
136
|
+
'combustivel', # Fuel type
|
137
|
+
'leilao', # Auction
|
138
|
+
'ceg', # CEG code
|
139
|
+
'ano_prev' # Expected year
|
140
|
+
]
|
141
|
+
|
142
|
+
# Filter columns that actually exist in the dataset
|
143
|
+
existing_columns = ['geometry'] + [col for col in columns_to_keep[1:] if col in gdf.columns]
|
144
|
+
if len(existing_columns) <= 1:
|
145
|
+
if verbose:
|
146
|
+
print("Warning: No matching columns found for simplified version. Returning all columns.")
|
147
|
+
else:
|
148
|
+
gdf = gdf[existing_columns]
|
149
|
+
|
150
|
+
except Exception as e:
|
151
|
+
raise Exception(f"Error downloading or processing planned biomass thermoelectric power plants data: {str(e)}")
|
152
|
+
|
153
|
+
return gdf
|
154
|
+
|
155
|
+
if __name__ == '__main__':
|
156
|
+
try:
|
157
|
+
biomass_ute_data = read_planned_biomass_ute(verbose=True)
|
158
|
+
print(f"Downloaded planned biomass thermoelectric power plants data with {len(biomass_ute_data)} records and {len(biomass_ute_data.columns)} columns")
|
159
|
+
|
160
|
+
# Test simplified version
|
161
|
+
simplified_data = read_planned_biomass_ute(simplified=True)
|
162
|
+
print(f"Simplified data has {len(simplified_data.columns)} columns: {simplified_data.columns.tolist()}")
|
163
|
+
except Exception as e:
|
164
|
+
print(f"Error: {str(e)}")
|
165
|
+
import traceback
|
166
|
+
traceback.print_exc()
|
@@ -0,0 +1,166 @@
|
|
1
|
+
import geopandas as gpd
|
2
|
+
import os
|
3
|
+
import tempfile
|
4
|
+
import urllib.parse
|
5
|
+
import requests
|
6
|
+
import shutil
|
7
|
+
from zipfile import ZipFile
|
8
|
+
from pathlib import Path
|
9
|
+
from io import BytesIO
|
10
|
+
import warnings
|
11
|
+
import json
|
12
|
+
|
13
|
+
def read_planned_cgh(simplified=False, verbose=False):
|
14
|
+
"""Download Planned Mini Hydroelectric Power Plants (CGH) data from EPE.
|
15
|
+
|
16
|
+
This function downloads and processes planned mini hydroelectric power plants (CGH) data from EPE
|
17
|
+
(Energy Research Company). The data includes information about planned mini hydroelectric
|
18
|
+
power generation projects across Brazil.
|
19
|
+
Original source: EPE (Empresa de Pesquisa Energética)
|
20
|
+
|
21
|
+
Parameters
|
22
|
+
----------
|
23
|
+
simplified : boolean, by default False
|
24
|
+
If True, returns a simplified version of the dataset with fewer columns
|
25
|
+
verbose : boolean, by default False
|
26
|
+
If True, prints detailed information about the download process
|
27
|
+
|
28
|
+
Returns
|
29
|
+
-------
|
30
|
+
gpd.GeoDataFrame
|
31
|
+
Geodataframe with planned mini hydroelectric power plants data
|
32
|
+
|
33
|
+
Example
|
34
|
+
-------
|
35
|
+
>>> from tunned_geobr import read_planned_cgh
|
36
|
+
|
37
|
+
# Read planned mini hydroelectric power plants data
|
38
|
+
>>> planned_cgh = read_planned_cgh()
|
39
|
+
"""
|
40
|
+
|
41
|
+
# URL for the EPE geoserver
|
42
|
+
url = r"https://gisepeprd2.epe.gov.br/arcgis/rest/services/Download_Dados_Webmap_EPE/GPServer/Extract%20Data%20Task/execute?f=json&env%3AoutSR=102100&Layers_to_Clip=%5B%22CGH%20-%20Expans%C3%A3o%20Planejada%22%5D&Area_of_Interest=%7B%22geometryType%22%3A%22esriGeometryPolygon%22%2C%22features%22%3A%5B%7B%22geometry%22%3A%7B%22rings%22%3A%5B%5B%5B-8655251.47456396%2C-4787514.465591563%5D%2C%5B-8655251.47456396%2C1229608.401015912%5D%2C%5B-3508899.2341809804%2C1229608.401015912%5D%2C%5B-3508899.2341809804%2C-4787514.465591563%5D%2C%5B-8655251.47456396%2C-4787514.465591563%5D%5D%5D%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%7D%7D%7D%5D%2C%22sr%22%3A%7B%22wkid%22%3A102100%7D%7D&Feature_Format=Shapefile%20-%20SHP%20-%20.shp&Raster_Format=Tagged%20Image%20File%20Format%20-%20TIFF%20-%20.tif"
|
43
|
+
|
44
|
+
try:
|
45
|
+
# Disable SSL verification warning
|
46
|
+
warnings.filterwarnings('ignore', message='Unverified HTTPS request')
|
47
|
+
|
48
|
+
if verbose:
|
49
|
+
print("Requesting data from EPE server...")
|
50
|
+
|
51
|
+
response = requests.get(url, timeout=60, verify=False)
|
52
|
+
if not response.ok:
|
53
|
+
raise Exception(f"Error getting JSON response: {response.status_code}")
|
54
|
+
|
55
|
+
json_response = response.json()
|
56
|
+
|
57
|
+
if verbose:
|
58
|
+
print(f"JSON response received: {json.dumps(json_response, indent=2)[:500]}...")
|
59
|
+
|
60
|
+
if 'results' not in json_response or len(json_response['results']) == 0:
|
61
|
+
raise Exception("Invalid JSON response structure")
|
62
|
+
|
63
|
+
if 'value' not in json_response['results'][0] or 'url' not in json_response['results'][0]['value']:
|
64
|
+
raise Exception("URL not found in JSON response")
|
65
|
+
|
66
|
+
file_url = json_response['results'][0]['value']['url']
|
67
|
+
|
68
|
+
if verbose:
|
69
|
+
print(f"Downloading file from: {file_url}")
|
70
|
+
|
71
|
+
file_response = requests.get(file_url, stream=True, timeout=60, verify=False)
|
72
|
+
if not file_response.ok:
|
73
|
+
raise Exception(f"Error downloading file: {file_response.status_code}")
|
74
|
+
|
75
|
+
# Check if content is actually a zip file
|
76
|
+
content = file_response.content
|
77
|
+
if len(content) < 100:
|
78
|
+
if verbose:
|
79
|
+
print(f"Warning: Downloaded content is very small ({len(content)} bytes)")
|
80
|
+
print(f"Content preview: {content[:100]}")
|
81
|
+
|
82
|
+
# Create a temporary directory to extract the files
|
83
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
84
|
+
if verbose:
|
85
|
+
print(f"Extracting files to temporary directory: {temp_dir}")
|
86
|
+
|
87
|
+
try:
|
88
|
+
# Extract the zip file
|
89
|
+
with ZipFile(BytesIO(content)) as zip_ref:
|
90
|
+
zip_ref.extractall(temp_dir)
|
91
|
+
|
92
|
+
if verbose:
|
93
|
+
print(f"Files in zip: {zip_ref.namelist()}")
|
94
|
+
except Exception as zip_error:
|
95
|
+
if verbose:
|
96
|
+
print(f"Error extracting zip: {str(zip_error)}")
|
97
|
+
print(f"Saving content to debug.zip for inspection")
|
98
|
+
with open("debug.zip", "wb") as f:
|
99
|
+
f.write(content)
|
100
|
+
raise Exception(f"Failed to extract zip file: {str(zip_error)}")
|
101
|
+
|
102
|
+
# Find the shapefile
|
103
|
+
all_files = os.listdir(temp_dir)
|
104
|
+
if verbose:
|
105
|
+
print(f"Files in temp directory: {all_files}")
|
106
|
+
|
107
|
+
shp_files = [f for f in all_files if f.endswith('.shp')]
|
108
|
+
if not shp_files:
|
109
|
+
# Try looking in subdirectories
|
110
|
+
for root, dirs, files in os.walk(temp_dir):
|
111
|
+
shp_files.extend([os.path.join(root, f) for f in files if f.endswith('.shp')])
|
112
|
+
|
113
|
+
if not shp_files:
|
114
|
+
raise Exception("No shapefile found in the downloaded data")
|
115
|
+
|
116
|
+
# Read the shapefile
|
117
|
+
shp_path = shp_files[0] if os.path.isabs(shp_files[0]) else os.path.join(temp_dir, shp_files[0])
|
118
|
+
if verbose:
|
119
|
+
print(f"Reading shapefile: {shp_path}")
|
120
|
+
|
121
|
+
gdf = gpd.read_file(shp_path)
|
122
|
+
|
123
|
+
# Convert to SIRGAS 2000 (EPSG:4674)
|
124
|
+
gdf = gdf.to_crs(4674)
|
125
|
+
|
126
|
+
if verbose:
|
127
|
+
print(f"Data loaded successfully with {len(gdf)} records")
|
128
|
+
print(f"Columns: {gdf.columns.tolist()}")
|
129
|
+
|
130
|
+
if simplified:
|
131
|
+
# Keep only the most relevant columns
|
132
|
+
columns_to_keep = [
|
133
|
+
'geometry',
|
134
|
+
'nome', # Power plant name
|
135
|
+
'potencia', # Capacity in MW
|
136
|
+
'rio', # River name
|
137
|
+
'bacia', # Basin
|
138
|
+
'sub_bacia', # Sub-basin
|
139
|
+
'ano_prev' # Expected year
|
140
|
+
]
|
141
|
+
|
142
|
+
# Filter columns that actually exist in the dataset
|
143
|
+
existing_columns = ['geometry'] + [col for col in columns_to_keep[1:] if col in gdf.columns]
|
144
|
+
if len(existing_columns) <= 1:
|
145
|
+
if verbose:
|
146
|
+
print("Warning: No matching columns found for simplified version. Returning all columns.")
|
147
|
+
else:
|
148
|
+
gdf = gdf[existing_columns]
|
149
|
+
|
150
|
+
except Exception as e:
|
151
|
+
raise Exception(f"Error downloading or processing planned mini hydroelectric power plants data: {str(e)}")
|
152
|
+
|
153
|
+
return gdf
|
154
|
+
|
155
|
+
if __name__ == '__main__':
|
156
|
+
try:
|
157
|
+
cgh_data = read_planned_cgh(verbose=True)
|
158
|
+
print(f"Downloaded planned mini hydroelectric power plants data with {len(cgh_data)} records and {len(cgh_data.columns)} columns")
|
159
|
+
|
160
|
+
# Test simplified version
|
161
|
+
simplified_data = read_planned_cgh(simplified=True)
|
162
|
+
print(f"Simplified data has {len(simplified_data.columns)} columns: {simplified_data.columns.tolist()}")
|
163
|
+
except Exception as e:
|
164
|
+
print(f"Error: {str(e)}")
|
165
|
+
import traceback
|
166
|
+
traceback.print_exc()
|
@@ -0,0 +1,165 @@
|
|
1
|
+
import geopandas as gpd
|
2
|
+
import os
|
3
|
+
import tempfile
|
4
|
+
import urllib.parse
|
5
|
+
import requests
|
6
|
+
import shutil
|
7
|
+
from zipfile import ZipFile
|
8
|
+
from pathlib import Path
|
9
|
+
from io import BytesIO
|
10
|
+
import warnings
|
11
|
+
import json
|
12
|
+
|
13
|
+
def read_planned_eolic(simplified=False, verbose=False):
|
14
|
+
"""Download Planned Eolic Power Plants data from EPE.
|
15
|
+
|
16
|
+
This function downloads and processes planned eolic (wind) power plants data from EPE
|
17
|
+
(Energy Research Company). The data includes information about planned wind power
|
18
|
+
generation projects across Brazil.
|
19
|
+
Original source: EPE (Empresa de Pesquisa Energética)
|
20
|
+
|
21
|
+
Parameters
|
22
|
+
----------
|
23
|
+
simplified : boolean, by default False
|
24
|
+
If True, returns a simplified version of the dataset with fewer columns
|
25
|
+
verbose : boolean, by default False
|
26
|
+
If True, prints detailed information about the download process
|
27
|
+
|
28
|
+
Returns
|
29
|
+
-------
|
30
|
+
gpd.GeoDataFrame
|
31
|
+
Geodataframe with planned eolic power plants data
|
32
|
+
|
33
|
+
Example
|
34
|
+
-------
|
35
|
+
>>> from tunned_geobr import read_planned_eolic
|
36
|
+
|
37
|
+
# Read planned eolic power plants data
|
38
|
+
>>> planned_eolic = read_planned_eolic()
|
39
|
+
"""
|
40
|
+
|
41
|
+
# URL for the EPE geoserver WFS service
|
42
|
+
url = r"https://gisepeprd2.epe.gov.br/arcgis/rest/services/Download_Dados_Webmap_EPE/GPServer/Extract%20Data%20Task/execute?f=json&env%3AoutSR=102100&Layers_to_Clip=%5B%22EOL%20-%20Expans%C3%A3o%20Planejada%22%5D&Area_of_Interest=%7B%22geometryType%22%3A%22esriGeometryPolygon%22%2C%22features%22%3A%5B%7B%22geometry%22%3A%7B%22rings%22%3A%5B%5B%5B-8202935.359686549%2C-4447637.219321614%5D%2C%5B-8202935.359686549%2C1119424.4247428626%5D%2C%5B-3487076.4626055676%2C1119424.4247428626%5D%2C%5B-3487076.4626055676%2C-4447637.219321614%5D%2C%5B-8202935.359686549%2C-4447637.219321614%5D%5D%5D%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%7D%7D%7D%5D%2C%22sr%22%3A%7B%22wkid%22%3A102100%7D%7D&Feature_Format=Shapefile%20-%20SHP%20-%20.shp&Raster_Format=Tagged%20Image%20File%20Format%20-%20TIFF%20-%20.tif"
|
43
|
+
|
44
|
+
try:
|
45
|
+
# Disable SSL verification warning
|
46
|
+
warnings.filterwarnings('ignore', message='Unverified HTTPS request')
|
47
|
+
|
48
|
+
if verbose:
|
49
|
+
print("Requesting data from EPE server...")
|
50
|
+
|
51
|
+
response = requests.get(url, timeout=60, verify=False)
|
52
|
+
if not response.ok:
|
53
|
+
raise Exception(f"Error getting JSON response: {response.status_code}")
|
54
|
+
|
55
|
+
json_response = response.json()
|
56
|
+
|
57
|
+
if verbose:
|
58
|
+
print(f"JSON response received: {json.dumps(json_response, indent=2)[:500]}...")
|
59
|
+
|
60
|
+
if 'results' not in json_response or len(json_response['results']) == 0:
|
61
|
+
raise Exception("Invalid JSON response structure")
|
62
|
+
|
63
|
+
if 'value' not in json_response['results'][0] or 'url' not in json_response['results'][0]['value']:
|
64
|
+
raise Exception("URL not found in JSON response")
|
65
|
+
|
66
|
+
file_url = json_response['results'][0]['value']['url']
|
67
|
+
|
68
|
+
if verbose:
|
69
|
+
print(f"Downloading file from: {file_url}")
|
70
|
+
|
71
|
+
file_response = requests.get(file_url, stream=True, timeout=60, verify=False)
|
72
|
+
if not file_response.ok:
|
73
|
+
raise Exception(f"Error downloading file: {file_response.status_code}")
|
74
|
+
|
75
|
+
# Check if content is actually a zip file
|
76
|
+
content = file_response.content
|
77
|
+
if len(content) < 100:
|
78
|
+
if verbose:
|
79
|
+
print(f"Warning: Downloaded content is very small ({len(content)} bytes)")
|
80
|
+
print(f"Content preview: {content[:100]}")
|
81
|
+
|
82
|
+
# Create a temporary directory to extract the files
|
83
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
84
|
+
if verbose:
|
85
|
+
print(f"Extracting files to temporary directory: {temp_dir}")
|
86
|
+
|
87
|
+
try:
|
88
|
+
# Extract the zip file
|
89
|
+
with ZipFile(BytesIO(content)) as zip_ref:
|
90
|
+
zip_ref.extractall(temp_dir)
|
91
|
+
|
92
|
+
if verbose:
|
93
|
+
print(f"Files in zip: {zip_ref.namelist()}")
|
94
|
+
except Exception as zip_error:
|
95
|
+
if verbose:
|
96
|
+
print(f"Error extracting zip: {str(zip_error)}")
|
97
|
+
print(f"Saving content to debug.zip for inspection")
|
98
|
+
with open("debug.zip", "wb") as f:
|
99
|
+
f.write(content)
|
100
|
+
raise Exception(f"Failed to extract zip file: {str(zip_error)}")
|
101
|
+
|
102
|
+
# Find the shapefile
|
103
|
+
all_files = os.listdir(temp_dir)
|
104
|
+
if verbose:
|
105
|
+
print(f"Files in temp directory: {all_files}")
|
106
|
+
|
107
|
+
shp_files = [f for f in all_files if f.endswith('.shp')]
|
108
|
+
if not shp_files:
|
109
|
+
# Try looking in subdirectories
|
110
|
+
for root, dirs, files in os.walk(temp_dir):
|
111
|
+
shp_files.extend([os.path.join(root, f) for f in files if f.endswith('.shp')])
|
112
|
+
|
113
|
+
if not shp_files:
|
114
|
+
raise Exception("No shapefile found in the downloaded data")
|
115
|
+
|
116
|
+
# Read the shapefile
|
117
|
+
shp_path = shp_files[0] if os.path.isabs(shp_files[0]) else os.path.join(temp_dir, shp_files[0])
|
118
|
+
if verbose:
|
119
|
+
print(f"Reading shapefile: {shp_path}")
|
120
|
+
|
121
|
+
gdf = gpd.read_file(shp_path)
|
122
|
+
|
123
|
+
# Convert to SIRGAS 2000 (EPSG:4674)
|
124
|
+
gdf = gdf.to_crs(4674)
|
125
|
+
|
126
|
+
if verbose:
|
127
|
+
print(f"Data loaded successfully with {len(gdf)} records")
|
128
|
+
print(f"Columns: {gdf.columns.tolist()}")
|
129
|
+
|
130
|
+
if simplified:
|
131
|
+
# Keep only the most relevant columns
|
132
|
+
columns_to_keep = [
|
133
|
+
'geometry',
|
134
|
+
'nome', # Power plant name
|
135
|
+
'potencia', # Capacity in MW
|
136
|
+
'leilao', # Auction
|
137
|
+
'ceg', # CEG code
|
138
|
+
'ano_prev' # Expected year
|
139
|
+
]
|
140
|
+
|
141
|
+
# Filter columns that actually exist in the dataset
|
142
|
+
existing_columns = ['geometry'] + [col for col in columns_to_keep[1:] if col in gdf.columns]
|
143
|
+
if len(existing_columns) <= 1:
|
144
|
+
if verbose:
|
145
|
+
print("Warning: No matching columns found for simplified version. Returning all columns.")
|
146
|
+
else:
|
147
|
+
gdf = gdf[existing_columns]
|
148
|
+
|
149
|
+
except Exception as e:
|
150
|
+
raise Exception(f"Error downloading or processing planned eolic power plants data: {str(e)}")
|
151
|
+
|
152
|
+
return gdf
|
153
|
+
|
154
|
+
if __name__ == '__main__':
|
155
|
+
try:
|
156
|
+
eolic_data = read_planned_eolic(verbose=True)
|
157
|
+
print(f"Downloaded planned eolic power plants data with {len(eolic_data)} records and {len(eolic_data.columns)} columns")
|
158
|
+
|
159
|
+
# Test simplified version
|
160
|
+
simplified_data = read_planned_eolic(simplified=True)
|
161
|
+
print(f"Simplified data has {len(simplified_data.columns)} columns: {simplified_data.columns.tolist()}")
|
162
|
+
except Exception as e:
|
163
|
+
print(f"Error: {str(e)}")
|
164
|
+
import traceback
|
165
|
+
traceback.print_exc()
|
@@ -0,0 +1,166 @@
|
|
1
|
+
import geopandas as gpd
|
2
|
+
import os
|
3
|
+
import tempfile
|
4
|
+
import urllib.parse
|
5
|
+
import requests
|
6
|
+
import shutil
|
7
|
+
from zipfile import ZipFile
|
8
|
+
from pathlib import Path
|
9
|
+
from io import BytesIO
|
10
|
+
import warnings
|
11
|
+
import json
|
12
|
+
|
13
|
+
def read_planned_fossile_ute(simplified=False, verbose=False):
|
14
|
+
"""Download Planned Fossil Thermoelectric Power Plants data from EPE.
|
15
|
+
|
16
|
+
This function downloads and processes planned fossil thermoelectric power plants data from EPE
|
17
|
+
(Energy Research Company). The data includes information about planned fossil thermoelectric
|
18
|
+
power generation projects across Brazil.
|
19
|
+
Original source: EPE (Empresa de Pesquisa Energética)
|
20
|
+
|
21
|
+
Parameters
|
22
|
+
----------
|
23
|
+
simplified : boolean, by default False
|
24
|
+
If True, returns a simplified version of the dataset with fewer columns
|
25
|
+
verbose : boolean, by default False
|
26
|
+
If True, prints detailed information about the download process
|
27
|
+
|
28
|
+
Returns
|
29
|
+
-------
|
30
|
+
gpd.GeoDataFrame
|
31
|
+
Geodataframe with planned fossil thermoelectric power plants data
|
32
|
+
|
33
|
+
Example
|
34
|
+
-------
|
35
|
+
>>> from tunned_geobr import read_planned_fossile_ute
|
36
|
+
|
37
|
+
# Read planned fossil thermoelectric power plants data
|
38
|
+
>>> planned_fossile_ute = read_planned_fossile_ute()
|
39
|
+
"""
|
40
|
+
|
41
|
+
# URL for the EPE geoserver
|
42
|
+
url = r"https://gisepeprd2.epe.gov.br/arcgis/rest/services/Download_Dados_Webmap_EPE/GPServer/Extract%20Data%20Task/execute?f=json&env%3AoutSR=102100&Layers_to_Clip=%5B%22UTE%20F%C3%B3ssil%20-%20Expans%C3%A3o%20Planejada%22%5D&Area_of_Interest=%7B%22geometryType%22%3A%22esriGeometryPolygon%22%2C%22features%22%3A%5B%7B%22geometry%22%3A%7B%22rings%22%3A%5B%5B%5B-8655251.47456396%2C-4787514.465591563%5D%2C%5B-8655251.47456396%2C1229608.401015912%5D%2C%5B-3508899.2341809804%2C1229608.401015912%5D%2C%5B-3508899.2341809804%2C-4787514.465591563%5D%2C%5B-8655251.47456396%2C-4787514.465591563%5D%5D%5D%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%7D%7D%7D%5D%2C%22sr%22%3A%7B%22wkid%22%3A102100%7D%7D&Feature_Format=Shapefile%20-%20SHP%20-%20.shp&Raster_Format=Tagged%20Image%20File%20Format%20-%20TIFF%20-%20.tif"
|
43
|
+
|
44
|
+
try:
|
45
|
+
# Disable SSL verification warning
|
46
|
+
warnings.filterwarnings('ignore', message='Unverified HTTPS request')
|
47
|
+
|
48
|
+
if verbose:
|
49
|
+
print("Requesting data from EPE server...")
|
50
|
+
|
51
|
+
response = requests.get(url, timeout=60, verify=False)
|
52
|
+
if not response.ok:
|
53
|
+
raise Exception(f"Error getting JSON response: {response.status_code}")
|
54
|
+
|
55
|
+
json_response = response.json()
|
56
|
+
|
57
|
+
if verbose:
|
58
|
+
print(f"JSON response received: {json.dumps(json_response, indent=2)[:500]}...")
|
59
|
+
|
60
|
+
if 'results' not in json_response or len(json_response['results']) == 0:
|
61
|
+
raise Exception("Invalid JSON response structure")
|
62
|
+
|
63
|
+
if 'value' not in json_response['results'][0] or 'url' not in json_response['results'][0]['value']:
|
64
|
+
raise Exception("URL not found in JSON response")
|
65
|
+
|
66
|
+
file_url = json_response['results'][0]['value']['url']
|
67
|
+
|
68
|
+
if verbose:
|
69
|
+
print(f"Downloading file from: {file_url}")
|
70
|
+
|
71
|
+
file_response = requests.get(file_url, stream=True, timeout=60, verify=False)
|
72
|
+
if not file_response.ok:
|
73
|
+
raise Exception(f"Error downloading file: {file_response.status_code}")
|
74
|
+
|
75
|
+
# Check if content is actually a zip file
|
76
|
+
content = file_response.content
|
77
|
+
if len(content) < 100:
|
78
|
+
if verbose:
|
79
|
+
print(f"Warning: Downloaded content is very small ({len(content)} bytes)")
|
80
|
+
print(f"Content preview: {content[:100]}")
|
81
|
+
|
82
|
+
# Create a temporary directory to extract the files
|
83
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
84
|
+
if verbose:
|
85
|
+
print(f"Extracting files to temporary directory: {temp_dir}")
|
86
|
+
|
87
|
+
try:
|
88
|
+
# Extract the zip file
|
89
|
+
with ZipFile(BytesIO(content)) as zip_ref:
|
90
|
+
zip_ref.extractall(temp_dir)
|
91
|
+
|
92
|
+
if verbose:
|
93
|
+
print(f"Files in zip: {zip_ref.namelist()}")
|
94
|
+
except Exception as zip_error:
|
95
|
+
if verbose:
|
96
|
+
print(f"Error extracting zip: {str(zip_error)}")
|
97
|
+
print(f"Saving content to debug.zip for inspection")
|
98
|
+
with open("debug.zip", "wb") as f:
|
99
|
+
f.write(content)
|
100
|
+
raise Exception(f"Failed to extract zip file: {str(zip_error)}")
|
101
|
+
|
102
|
+
# Find the shapefile
|
103
|
+
all_files = os.listdir(temp_dir)
|
104
|
+
if verbose:
|
105
|
+
print(f"Files in temp directory: {all_files}")
|
106
|
+
|
107
|
+
shp_files = [f for f in all_files if f.endswith('.shp')]
|
108
|
+
if not shp_files:
|
109
|
+
# Try looking in subdirectories
|
110
|
+
for root, dirs, files in os.walk(temp_dir):
|
111
|
+
shp_files.extend([os.path.join(root, f) for f in files if f.endswith('.shp')])
|
112
|
+
|
113
|
+
if not shp_files:
|
114
|
+
raise Exception("No shapefile found in the downloaded data")
|
115
|
+
|
116
|
+
# Read the shapefile
|
117
|
+
shp_path = shp_files[0] if os.path.isabs(shp_files[0]) else os.path.join(temp_dir, shp_files[0])
|
118
|
+
if verbose:
|
119
|
+
print(f"Reading shapefile: {shp_path}")
|
120
|
+
|
121
|
+
gdf = gpd.read_file(shp_path)
|
122
|
+
|
123
|
+
# Convert to SIRGAS 2000 (EPSG:4674)
|
124
|
+
gdf = gdf.to_crs(4674)
|
125
|
+
|
126
|
+
if verbose:
|
127
|
+
print(f"Data loaded successfully with {len(gdf)} records")
|
128
|
+
print(f"Columns: {gdf.columns.tolist()}")
|
129
|
+
|
130
|
+
if simplified:
|
131
|
+
# Keep only the most relevant columns
|
132
|
+
columns_to_keep = [
|
133
|
+
'geometry',
|
134
|
+
'nome', # Power plant name
|
135
|
+
'potencia', # Capacity in MW
|
136
|
+
'combustivel', # Fuel type
|
137
|
+
'leilao', # Auction
|
138
|
+
'ceg', # CEG code
|
139
|
+
'ano_prev' # Expected year
|
140
|
+
]
|
141
|
+
|
142
|
+
# Filter columns that actually exist in the dataset
|
143
|
+
existing_columns = ['geometry'] + [col for col in columns_to_keep[1:] if col in gdf.columns]
|
144
|
+
if len(existing_columns) <= 1:
|
145
|
+
if verbose:
|
146
|
+
print("Warning: No matching columns found for simplified version. Returning all columns.")
|
147
|
+
else:
|
148
|
+
gdf = gdf[existing_columns]
|
149
|
+
|
150
|
+
except Exception as e:
|
151
|
+
raise Exception(f"Error downloading or processing planned fossil thermoelectric power plants data: {str(e)}")
|
152
|
+
|
153
|
+
return gdf
|
154
|
+
|
155
|
+
if __name__ == '__main__':
|
156
|
+
try:
|
157
|
+
fossile_ute_data = read_planned_fossile_ute(verbose=True)
|
158
|
+
print(f"Downloaded planned fossil thermoelectric power plants data with {len(fossile_ute_data)} records and {len(fossile_ute_data.columns)} columns")
|
159
|
+
|
160
|
+
# Test simplified version
|
161
|
+
simplified_data = read_planned_fossile_ute(simplified=True)
|
162
|
+
print(f"Simplified data has {len(simplified_data.columns)} columns: {simplified_data.columns.tolist()}")
|
163
|
+
except Exception as e:
|
164
|
+
print(f"Error: {str(e)}")
|
165
|
+
import traceback
|
166
|
+
traceback.print_exc()
|