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.
Files changed (67) hide show
  1. tunned_geobr/__init__.py +59 -1
  2. tunned_geobr/list_geobr.py +74 -3
  3. tunned_geobr/read_ama_anemometric_towers.py +119 -0
  4. tunned_geobr/read_areas_under_contract.py +129 -0
  5. tunned_geobr/read_biodiesel_plants.py +128 -0
  6. tunned_geobr/read_biomethane_plants.py +128 -0
  7. tunned_geobr/read_compression_stations.py +128 -0
  8. tunned_geobr/read_drainage_ducts.py +128 -0
  9. tunned_geobr/read_etanol_plants.py +128 -0
  10. tunned_geobr/read_existent_biomass_ute.py +128 -0
  11. tunned_geobr/read_existent_cgh.py +168 -0
  12. tunned_geobr/read_existent_eolic.py +165 -0
  13. tunned_geobr/read_existent_fossile_ute.py +128 -0
  14. tunned_geobr/read_existent_nuclear_ute.py +128 -0
  15. tunned_geobr/read_existent_pch.py +168 -0
  16. tunned_geobr/read_existent_solar.py +165 -0
  17. tunned_geobr/read_existent_substations.py +128 -0
  18. tunned_geobr/read_existent_transmission_lines.py +128 -0
  19. tunned_geobr/read_existent_uhe.py +168 -0
  20. tunned_geobr/read_exploration_production_environment.py +119 -0
  21. tunned_geobr/read_federal_union_areas.py +129 -0
  22. tunned_geobr/read_fuel_bases.py +128 -0
  23. tunned_geobr/read_gas_distribution_pipelines.py +128 -0
  24. tunned_geobr/read_gas_transport_pipelines.py +128 -0
  25. tunned_geobr/read_glp_bases.py +128 -0
  26. tunned_geobr/read_gnl_terminals.py +128 -0
  27. tunned_geobr/read_hydroelectric_feasibility_studies.py +119 -0
  28. tunned_geobr/read_hydroelectric_inventory_aai_studies.py +119 -0
  29. tunned_geobr/read_isolated_systems.py +128 -0
  30. tunned_geobr/read_natural_gas_delivery_points.py +128 -0
  31. tunned_geobr/read_natural_gas_processing_hub.py +128 -0
  32. tunned_geobr/read_og_basement.py +119 -0
  33. tunned_geobr/read_og_effective_geographic_basin.py +129 -0
  34. tunned_geobr/read_og_ipa_direct_evidence.py +119 -0
  35. tunned_geobr/read_og_ipa_exploratory_activity.py +119 -0
  36. tunned_geobr/read_og_ipa_exploratory_intensity.py +129 -0
  37. tunned_geobr/read_og_ipa_need_for_knowledge.py +119 -0
  38. tunned_geobr/read_og_ipa_prospectiveness.py +119 -0
  39. tunned_geobr/read_og_ipa_supply_infrastructure.py +119 -0
  40. tunned_geobr/read_og_legal_pre_salt_polygon.py +119 -0
  41. tunned_geobr/read_og_predominant_fluid_type.py +129 -0
  42. tunned_geobr/read_og_probabilistic_effective_basin.py +129 -0
  43. tunned_geobr/read_og_total_ipa.py +129 -0
  44. tunned_geobr/read_og_unconventional_resources.py +129 -0
  45. tunned_geobr/read_oil_and_derivatives_terminal.py +128 -0
  46. tunned_geobr/read_pan_strategic_areas 2.py +71 -0
  47. tunned_geobr/read_pio_ducts.py +128 -0
  48. tunned_geobr/read_pio_terminals.py +128 -0
  49. tunned_geobr/read_planned_biomass_ute.py +166 -0
  50. tunned_geobr/read_planned_cgh.py +166 -0
  51. tunned_geobr/read_planned_eolic.py +165 -0
  52. tunned_geobr/read_planned_fossile_ute.py +166 -0
  53. tunned_geobr/read_planned_nuclear_ute.py +165 -0
  54. tunned_geobr/read_planned_pch.py +166 -0
  55. tunned_geobr/read_planned_solar.py +165 -0
  56. tunned_geobr/read_planned_substations.py +164 -0
  57. tunned_geobr/read_planned_transmission_lines.py +165 -0
  58. tunned_geobr/read_planned_uhe.py +166 -0
  59. tunned_geobr/read_processing_facilities.py +128 -0
  60. tunned_geobr/read_sedimentary_basins.py +119 -0
  61. tunned_geobr/read_subsystem_interconnected.py +163 -0
  62. {tunned_geobr-0.2.2.dist-info → tunned_geobr-0.2.4.dist-info}/METADATA +1 -1
  63. {tunned_geobr-0.2.2.dist-info → tunned_geobr-0.2.4.dist-info}/RECORD +66 -8
  64. tunned_geobr/constants.py +0 -13
  65. {tunned_geobr-0.2.2.dist-info → tunned_geobr-0.2.4.dist-info}/WHEEL +0 -0
  66. {tunned_geobr-0.2.2.dist-info → tunned_geobr-0.2.4.dist-info}/entry_points.txt +0 -0
  67. {tunned_geobr-0.2.2.dist-info → tunned_geobr-0.2.4.dist-info}/licenses/LICENSE.txt +0 -0
@@ -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_nuclear_ute(simplified=False, verbose=False):
14
+ """Download Planned Nuclear Thermoelectric Power Plants data from EPE.
15
+
16
+ This function downloads and processes planned nuclear thermoelectric power plants data from EPE
17
+ (Energy Research Company). The data includes information about planned nuclear 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 nuclear thermoelectric power plants data
32
+
33
+ Example
34
+ -------
35
+ >>> from tunned_geobr import read_planned_nuclear_ute
36
+
37
+ # Read planned nuclear thermoelectric power plants data
38
+ >>> planned_nuclear_ute = read_planned_nuclear_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%20Nuclear%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
+ '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 nuclear thermoelectric power plants data: {str(e)}")
151
+
152
+ return gdf
153
+
154
+ if __name__ == '__main__':
155
+ try:
156
+ nuclear_ute_data = read_planned_nuclear_ute(verbose=True)
157
+ print(f"Downloaded planned nuclear thermoelectric power plants data with {len(nuclear_ute_data)} records and {len(nuclear_ute_data.columns)} columns")
158
+
159
+ # Test simplified version
160
+ simplified_data = read_planned_nuclear_ute(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_pch(simplified=False, verbose=False):
14
+ """Download Planned Small Hydroelectric Power Plants (PCH) data from EPE.
15
+
16
+ This function downloads and processes planned small hydroelectric power plants (PCH) data from EPE
17
+ (Energy Research Company). The data includes information about planned small 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 small hydroelectric power plants data
32
+
33
+ Example
34
+ -------
35
+ >>> from tunned_geobr import read_planned_pch
36
+
37
+ # Read planned small hydroelectric power plants data
38
+ >>> planned_pch = read_planned_pch()
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%22PCH%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 small hydroelectric power plants data: {str(e)}")
152
+
153
+ return gdf
154
+
155
+ if __name__ == '__main__':
156
+ try:
157
+ pch_data = read_planned_pch(verbose=True)
158
+ print(f"Downloaded planned small hydroelectric power plants data with {len(pch_data)} records and {len(pch_data.columns)} columns")
159
+
160
+ # Test simplified version
161
+ simplified_data = read_planned_pch(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_solar(simplified=False, verbose=False):
14
+ """Download Planned Solar Power Plants data from EPE.
15
+
16
+ This function downloads and processes planned solar power plants data from EPE
17
+ (Energy Research Company). The data includes information about planned solar power
18
+ generation facilities 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 solar power plants data
32
+
33
+ Example
34
+ -------
35
+ >>> from tunned_geobr import read_planned_solar
36
+
37
+ # Read planned solar power plants data
38
+ >>> planned_solar = read_planned_solar()
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%22UFV%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 based on actual data structure
132
+ columns_to_keep = [
133
+ 'geometry',
134
+ 'nome', # Plant name
135
+ 'potencia', # Power capacity
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 solar power plants data: {str(e)}")
151
+
152
+ return gdf
153
+
154
+ if __name__ == '__main__':
155
+ try:
156
+ solar_data = read_planned_solar(verbose=True)
157
+ print(f"Downloaded planned solar power plants data with {len(solar_data)} records and {len(solar_data.columns)} columns")
158
+
159
+ # Test simplified version
160
+ simplified_data = read_planned_solar(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,164 @@
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_substations(simplified=False, verbose=False):
14
+ """Download Planned Electrical Substations data from EPE.
15
+
16
+ This function downloads and processes planned electrical substations data from EPE
17
+ (Energy Research Company). The data includes information about planned electrical
18
+ substations 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 electrical substations data
32
+
33
+ Example
34
+ -------
35
+ >>> from tunned_geobr import read_planned_substations
36
+
37
+ # Read planned electrical substations data
38
+ >>> planned_substations = read_planned_substations()
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%22Subesta%C3%A7%C3%B5es%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', # Substation name
135
+ 'tensao', # Voltage level
136
+ 'ano_prev', # Expected year
137
+ 'situacao' # Status
138
+ ]
139
+
140
+ # Filter columns that actually exist in the dataset
141
+ existing_columns = ['geometry'] + [col for col in columns_to_keep[1:] if col in gdf.columns]
142
+ if len(existing_columns) <= 1:
143
+ if verbose:
144
+ print("Warning: No matching columns found for simplified version. Returning all columns.")
145
+ else:
146
+ gdf = gdf[existing_columns]
147
+
148
+ except Exception as e:
149
+ raise Exception(f"Error downloading or processing planned electrical substations data: {str(e)}")
150
+
151
+ return gdf
152
+
153
+ if __name__ == '__main__':
154
+ try:
155
+ substations_data = read_planned_substations(verbose=True)
156
+ print(f"Downloaded planned electrical substations data with {len(substations_data)} records and {len(substations_data.columns)} columns")
157
+
158
+ # Test simplified version
159
+ simplified_data = read_planned_substations(simplified=True)
160
+ print(f"Simplified data has {len(simplified_data.columns)} columns: {simplified_data.columns.tolist()}")
161
+ except Exception as e:
162
+ print(f"Error: {str(e)}")
163
+ import traceback
164
+ traceback.print_exc()