sazirarrwth99 commited on
Commit
9091025
·
1 Parent(s): b036217

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +421 -0
  2. requirements.txt +13 -0
app.py ADDED
@@ -0,0 +1,421 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ import sqlite3
4
+ import geopandas as gpd
5
+ import pandas as pd
6
+ # Import Meteostat library and dependencies
7
+ from datetime import datetime
8
+ import matplotlib.pyplot as plt
9
+ from meteostat import Point, Monthly
10
+ from tqdm import tqdm
11
+ import folium
12
+ from folium import GeoJson
13
+ import geopandas as gpd
14
+ import numpy as np
15
+ import matplotlib.colors
16
+
17
+ #remove pandas warning
18
+ pd.options.mode.chained_assignment = None # default='warn'
19
+ #remove geo pandas warning
20
+ gpd.options.use_pygeos = False
21
+ import pandas as pd
22
+ import logging
23
+ import modelchain_example as mc_e
24
+ from windpowerlib import WindTurbineCluster, WindFarm, TurbineClusterModelChain
25
+ #remove pandas warning
26
+ pd.options.mode.chained_assignment = None # default='warn'
27
+
28
+ import gradio as gr
29
+ import pandas as pd
30
+ import matplotlib.pyplot as plt
31
+
32
+ import gradio as gr
33
+ import folium
34
+ import geopandas as gpd
35
+ import pandas as pd
36
+ import numpy as np
37
+ from shapely.geometry import box
38
+ from branca.colormap import LinearColormap
39
+ import random
40
+ import io
41
+ import folium
42
+ from shapely.geometry import box
43
+ import geopandas as gpd
44
+ import pandas as pd
45
+ import numpy as np
46
+ import matplotlib.pyplot as plt
47
+ import matplotlib.colors
48
+ def wind_for_location(longitude, latitude):
49
+
50
+ start = datetime(2015, 1, 1)
51
+ end = datetime(2022, 12, 31)
52
+
53
+ # Create Point for Vancouver, BC
54
+ city = Point(latitude, longitude, 70)
55
+
56
+ # Get daily data for 2018
57
+ data = Monthly(city, start, end)
58
+ data = data.fetch()
59
+
60
+ windspeed = data['wspd']
61
+ max_windspeed = windspeed.mean()
62
+ return max_windspeed
63
+
64
+ def weather_for_location(longitude, latitude):
65
+
66
+ start = datetime(2015, 1, 1)
67
+ end = datetime(2022, 12, 31)
68
+
69
+ # Create Point for Vancouver, BC
70
+ city = Point(latitude, longitude, 70)
71
+
72
+ # Get daily data for 2018
73
+ data = Monthly(city, start, end)
74
+ data = data.fetch()
75
+ return data
76
+ def price_per_wind_power_plant(longitude):
77
+ return 500_000*abs((49-longitude))/47 + 50_000
78
+ import ast
79
+ def setup_wind_farm_cluster(num_of_plants,num_my_turbines=6,num_e126_turbines=6,location=(8,50)):
80
+ # Configure logging
81
+ logging.basicConfig(level=logging.DEBUG)
82
+ if isinstance(location, str):
83
+ location = ast.literal_eval(location)
84
+ # Get weather data
85
+ latitude = float(location[1])
86
+ longitude = float(location[0])
87
+ data = weather_for_location(longitude, latitude)
88
+ # Assuming 'data' is a DataFrame with columns ['tavg', 'wspd', 'pres']
89
+ data["roughness_length"] = 0.15
90
+ data["temperature"] = data["tavg"]
91
+ data["wind_speed"] = data["wspd"]
92
+ data["pressure"] = data["pres"]
93
+
94
+ # Create a multiindex
95
+ multiindex = pd.MultiIndex.from_tuples(
96
+ [('pressure', 0),
97
+ ('temperature', 2),
98
+ ('wind_speed', 2),
99
+ ('roughness_length', 0),
100
+ ('temperature', 10),
101
+ ('wind_speed', 10)],
102
+ names=['variable_name', 'height']
103
+ )
104
+
105
+ # Data for the multiindex DataFrame
106
+ data_WEATHER = {
107
+ ('pressure', 0): data["pressure"]*10,
108
+ ('temperature', 2): data["temperature"]*10,
109
+ ('wind_speed', 2): data["wind_speed"],
110
+ ('roughness_length', 0): [0.15] * len(data), # Assuming constant value for all rows
111
+ ('temperature', 10): data["temperature"]*10, # Assuming same temperature values for height 10
112
+ ('wind_speed', 10): data["wind_speed"] # Assuming same wind speed values for height 10
113
+ }
114
+
115
+ # Creating the MultiIndex DataFrame
116
+ df_multi = pd.DataFrame(data_WEATHER, index=data.index)
117
+ df_multi.ffill(inplace=True)
118
+ df_multi.bfill(inplace=True)
119
+ df_multi.dropna(inplace=True)
120
+ # Initialize wind turbines
121
+ my_turbine, e126, _ = mc_e.initialize_wind_turbines()
122
+
123
+
124
+ # Initialize WindFarm objects
125
+ farms = []
126
+ num_of_plants = int(num_of_plants)
127
+ num_my_turbines = int(num_my_turbines)
128
+ num_e126_turbines = int(num_e126_turbines)
129
+
130
+
131
+ for i in range(num_of_plants):
132
+ farm_data = {
133
+ 'name': f'example_farm_{i}',
134
+ 'wind_turbine_fleet': [my_turbine.to_group(num_my_turbines), e126.to_group(num_e126_turbines)],
135
+ 'efficiency': 0.9
136
+ }
137
+ farms.append(WindFarm(**farm_data))
138
+
139
+ # Initialize WindTurbineCluster
140
+ example_cluster = WindTurbineCluster(name='example_cluster', wind_farms=farms)
141
+
142
+ # Calculate power output for each farm and for the turbine cluster
143
+ for farm in farms:
144
+ mc_farm = TurbineClusterModelChain(farm).run_model(df_multi)
145
+ farm.power_output = mc_farm.power_output
146
+ farm.efficiency = 0.9 # Set efficiency
147
+
148
+ # Calculate power output for turbine_cluster with custom modelchain data
149
+ modelchain_data = {
150
+ 'wake_losses_model': 'wind_farm_efficiency',
151
+ 'smoothing': True,
152
+ 'block_width': 0.5,
153
+ 'standard_deviation_method': 'Staffell_Pfenninger',
154
+ 'smoothing_order': 'wind_farm_power_curves',
155
+ 'wind_speed_model': 'logarithmic',
156
+ 'density_model': 'ideal_gas',
157
+ 'temperature_model': 'linear_gradient',
158
+ 'power_output_model': 'power_curve',
159
+ 'density_correction': True,
160
+ 'obstacle_height': 0,
161
+ 'hellman_exp': None
162
+ }
163
+ mc_example_cluster = TurbineClusterModelChain(example_cluster, **modelchain_data).run_model(df_multi)
164
+ example_cluster.power_output = mc_example_cluster.power_output
165
+ # try to import matplotlib
166
+ logging.getLogger().setLevel(logging.WARNING)
167
+ from matplotlib import pyplot as plt
168
+ # matplotlib inline needed in notebook to plot inline
169
+ %matplotlib inline
170
+ df = example_cluster.power_output
171
+ #make seriesto dataframe
172
+ df = df.to_frame()
173
+ df["Time"] = df.index
174
+ df["example_cluster"] = df[df.columns[0]]
175
+
176
+ #rename column
177
+ # Plotting Function
178
+ plt.figure(figsize=(6,4))
179
+ plt.plot(df["Time"], df['example_cluster'], label='example_cluster')
180
+ plt.xlabel('Time')
181
+ plt.ylabel('Forecasted Power Output in W based on historical weather data')
182
+ fig_1 = plt.gcf()
183
+ plt.figure(figsize=(6,4))
184
+ example_cluster.power_curve.plot(
185
+ x='wind_speed', y='value', style='*')
186
+ plt.title('Power Curve of chosen Plant in regards to wind speed')
187
+ plt.xlabel('Wind speed in m/s')
188
+ plt.ylabel('Power in W')
189
+ fig_2 = plt.gcf()
190
+
191
+ #plot the historical weather data
192
+ plt.figure(figsize=(6,4))
193
+ plt.plot(data["tavg"], label='Temperature')
194
+ plt.plot(data["wspd"], label='Wind Speed')
195
+ plt.plot(data["pres"]*0.01, label='Pressure/100')
196
+ plt.title('Historical Weather Data used for Forecasting')
197
+ plt.xlabel('Time')
198
+ plt.ylabel('Historical Weather Data')
199
+ plt.legend()
200
+ fig_3 = plt.gcf()
201
+
202
+ return fig_1, fig_2, fig_3, example_cluster
203
+
204
+
205
+
206
+ # Your existing code to generate the map
207
+ def generate_germany_wind_map(chosen_location_long, chosen_location_lat):
208
+
209
+
210
+ # Load the map of Germany
211
+ germany_map = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')).query('name == "Germany"')
212
+
213
+ # Getting Germany's boundaries
214
+ minx, miny, maxx, maxy = germany_map.total_bounds
215
+
216
+ # Dividing Germany into a grid of 10x10
217
+ num_squares_side = 20
218
+ x_step = (maxx - minx) / num_squares_side
219
+ y_step = (maxy - miny) / num_squares_side
220
+
221
+ # Create a DataFrame to hold square polygons and their colors
222
+ if 1==1:
223
+
224
+ squares_df = pd.DataFrame(columns=['geometry', 'color'])
225
+
226
+ # Create the squares and assign random colors
227
+ for i in range(num_squares_side):
228
+ for j in range(num_squares_side):
229
+ square = box(minx + i * x_step, miny + j * y_step, minx + (i+1) * x_step, miny + (j+1) * y_step)
230
+ # Check if the square intersects with Germany's boundary
231
+ if germany_map.intersects(square).any():
232
+ squares_df = squares_df.append({'geometry': square, 'color': np.random.randint(0, 100)}, ignore_index=True)
233
+ squares_df["center"] = 0
234
+ squares_df["longitude"] = 0
235
+ squares_df["latitude"] = 0
236
+ squares_df["windspeed"] = 0
237
+ for i in tqdm(range(len(squares_df))):
238
+ squares_df["center"][i] = squares_df["geometry"][i].centroid
239
+ squares_df["longitude"][i] = squares_df["center"][i].x
240
+ squares_df["latitude"][i] = squares_df["center"][i].y
241
+ squares_df["windspeed"][i] = wind_for_location(squares_df["longitude"][i], squares_df["latitude"][i])
242
+ #make color the
243
+ squares_df["color"] =squares_df["windspeed"].copy()
244
+ #standardize the color based on standard deviation
245
+ #squares_df["color"] = (squares_df["color"] - squares_df["color"].mean())/squares_df["color"].std()
246
+
247
+
248
+ squares_df.ffill(inplace=True)
249
+ squares_df["color"] = squares_df["color"]
250
+
251
+
252
+ # Convert squares DataFrame to GeoDataFrame
253
+ squares_gdf = gpd.GeoDataFrame(squares_df, geometry='geometry')
254
+
255
+ # Create a Folium map centered on Germany
256
+ m = folium.Map(location=[(maxy + miny) / 2, (maxx + minx) / 2], zoom_start=6,tiles='cartodbpositron')
257
+
258
+ # Add Germany's borders to the map
259
+ folium.GeoJson(germany_map['geometry'], style_function=lambda feature: {
260
+ 'fillColor': '#ffff00',
261
+ 'color': '#000000',
262
+ 'weight': 1,
263
+ 'fillOpacity': 0,
264
+ }).add_to(m)
265
+
266
+ #add
267
+
268
+ from branca.colormap import LinearColormap
269
+
270
+ from branca.colormap import LinearColormap
271
+ import matplotlib
272
+
273
+
274
+
275
+
276
+ from branca.colormap import LinearColormap
277
+
278
+ # Define your colormap
279
+ colormap = LinearColormap(['#f7fbff', '#08306b'], vmin=7, vmax=20, caption="Mean Wind speed [m/s]]")
280
+ m.add_child(colormap)
281
+
282
+
283
+ # Add each square to the map with a color
284
+ for _, row in squares_gdf.iterrows():
285
+ # Normalize color value within the range of your colormap
286
+ #normalized_color = normalize(row['color'], vmin=5, vmax=50)
287
+
288
+ # Get color from colormap
289
+ color = colormap(row['color'])
290
+
291
+ folium.GeoJson(row['geometry'], style_function=lambda feature, color=color: {
292
+ 'fillColor': color,
293
+ 'color': color,
294
+ 'weight': 1,
295
+ 'fillOpacity': 0.5,
296
+ }).add_to(m)
297
+ #get a random point from germany_map.geometry[121]
298
+ #add 100 random points with price per wind power plant
299
+ import random
300
+ from shapely.geometry import Polygon
301
+ import shapely
302
+ polygon = Polygon(germany_map.geometry[121])
303
+ def generate_random_points(polygon, num_points):
304
+ points = []
305
+ min_x, min_y, max_x, max_y = polygon.bounds
306
+ while len(points) < num_points:
307
+ random_point = shapely.geometry.Point(random.uniform(min_x, max_x), random.uniform(min_y, max_y))
308
+ if polygon.contains(random_point):
309
+ points.append(random_point)
310
+ return points
311
+
312
+ points = generate_random_points(polygon, 100)
313
+
314
+ # Define your colormap, red to white
315
+ colormap_new_prices = LinearColormap(['green', 'red'], vmin=50000, vmax=100000, caption="Price per wind power plant (Only Land) [€]")
316
+ m.add_child(colormap_new_prices)
317
+
318
+ for point_german in points:
319
+ #get longitude and latitude
320
+ lon_point = point_german.x
321
+ lat_point = point_german.y
322
+ #get the price per wind power plant
323
+ price = price_per_wind_power_plant(lat_point)
324
+ #colorize the point based on the price
325
+ color = colormap_new_prices(price)
326
+ #add the point to the map
327
+ folium.CircleMarker(location=[lat_point, lon_point], radius=5, color=color, fill=True,popup=price).add_to(m)
328
+ #add the price to the map
329
+ #add the wind speed to the map
330
+ #get the closest point to the chosen location
331
+ from shapely.ops import nearest_points
332
+ #create a point
333
+ point = shapely.geometry.Point(chosen_location_long, chosen_location_lat)
334
+ #get the closest point
335
+ nearest_geoms = nearest_points(point, germany_map.geometry[121])
336
+ #get the closest point
337
+ nearest_point = nearest_geoms[1]
338
+ #get longitude and latitude
339
+ lon_point = nearest_point.x
340
+ lat_point = nearest_point.y
341
+ #add as big marker
342
+ folium.CircleMarker(location=[lat_point, lon_point], radius=10, color="blue", fill=True,popup="Chosen Location").add_to(m)
343
+
344
+
345
+
346
+ return m._repr_html_(), lon_point, lat_point
347
+
348
+ import json
349
+ from llamaapi import LlamaAPI
350
+
351
+
352
+
353
+ def generate_all(str_user_query):
354
+ # Initialize the llamaapi with your api_token
355
+ llama = LlamaAPI("LL-19li1nMIQLwltTkGRrN9vrfGgPAPZt2VKkW9rhWGt2lD6nDl6xrnPfEQ3C1X3UpO")
356
+
357
+ # Define your API request
358
+ api_request_json_select_wind_power_output = {
359
+ "messages": [
360
+ {"role": "user", "content": f"I want to build a windfarm with 25 Wind Power turbines in nothern Germany?"},
361
+ ],
362
+ "functions": [
363
+ {
364
+ "name": "get_wind_power_estimation",
365
+ "description": "Get the a simulation of the wind power output for a wind power plant",
366
+ "parameters": {
367
+ "type": "object",
368
+ "properties": {
369
+ "number_power_plants": {
370
+ "type": "number",
371
+ "description": "How many power plants do you want to build?",
372
+ },
373
+ "num_my_turbine_per_plant": {
374
+ "type": "number",
375
+ "description": "How many of tubine my_turbine do you want to build per plant? Default six.",
376
+ },
377
+ "num_e126_turbine_per_plant": {
378
+ "type": "number",
379
+ "description": "How many of tubine e126 do you want to build per plant? Default six.",
380
+ },
381
+ "latitude": {
382
+ "type": "number",
383
+ "description": "The longitude of the location of the wind power plant",
384
+ },
385
+ "longitude": {
386
+ "type": "number",
387
+ "description": "The longitude of the location of the wind power plant",
388
+ },
389
+ },
390
+ },
391
+ "required": ["number_power_plants", "num_my_turbine_per_plant", "num_e126_turbine_per_plant", "latitude", "longitude"],
392
+ }
393
+ ],
394
+ "stream": False,
395
+ "function_call": "get_wind_power_estimation",
396
+ }
397
+
398
+ # Make your request and handle the response
399
+ response = llama.run(api_request_json_select_wind_power_output)
400
+ output_llama = json.dumps(response.json(), indent=2)
401
+ dict_llama = dict(response.json())
402
+ dict_function = dict_llama["choices"][0]["message"]["function_call"]["arguments"]
403
+ fig_1, fig_2, fig_3, cluster = setup_wind_farm_cluster(dict_function["number_power_plants"],dict_function["num_my_turbine_per_plant"],dict_function["num_e126_turbine_per_plant"],(dict_function["longitude"],dict_function["latitude"]))
404
+ html_1, lon_point, lat_point = generate_germany_wind_map(dict_function["longitude"],dict_function["latitude"])
405
+
406
+ int_output = int(cluster.power_curve["value"].mean())
407
+ #generate a text output
408
+ text_output = f"Based on the historical weather data, the wind power output of the wind power plant would be {int_output}W on average. The power curve of the chosen wind power plant is shown in the second figure. The historical weather data is shown in the third figure. It would cost {int(dict_function['number_power_plants'])*price_per_wind_power_plant(lat_point)} € to get the land for the wind power plant. The chosen location is shown in the map below. It would be located in the blue circle. The wind speed in the area is {wind_for_location(lon_point, lat_point)} m/s. Please ask if you have any questions or need more information."
409
+ return text_output, html_1, fig_1, fig_2, fig_3
410
+ # Create the Gradio interface
411
+ iface = gr.Interface(
412
+ fn=generate_all,
413
+ inputs=["text"], # Input is a text box
414
+ outputs=["text",gr.HTML(), "plot", "plot", "plot"], # Output is HTML
415
+ title="Wind Power Plant Location Finder",
416
+ description="Just tell me what you need, one example could be: I want to build a windfarm with 25 Wind Power turbines in nothern Germany."
417
+ )
418
+
419
+
420
+ if __name__ == "__main__":
421
+ iface.launch()
requirements.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ numpy
2
+ matplotlib
3
+ geopandas
4
+ pandas==1.5.3
5
+ meteostat
6
+ tqdm
7
+ folium
8
+ matplotlib
9
+ windpowerlib
10
+ gradio
11
+ branca
12
+ shapely
13
+ llamaapi