File size: 16,130 Bytes
9091025
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7215ea6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
import numpy as np
import matplotlib.pyplot as plt
import sqlite3
import geopandas as gpd
import pandas as pd
# Import Meteostat library and dependencies
from datetime import datetime
import matplotlib.pyplot as plt
from meteostat import Point, Monthly
from tqdm import tqdm
import folium
from folium import GeoJson
import geopandas as gpd
import numpy as np
import matplotlib.colors

#remove pandas warning
pd.options.mode.chained_assignment = None  # default='warn'
#remove geo pandas warning
gpd.options.use_pygeos = False
import pandas as pd
import logging
import modelchain_example as mc_e
from windpowerlib import WindTurbineCluster, WindFarm, TurbineClusterModelChain
#remove pandas warning
pd.options.mode.chained_assignment = None  # default='warn'

import gradio as gr
import pandas as pd
import matplotlib.pyplot as plt

import gradio as gr
import folium
import geopandas as gpd
import pandas as pd
import numpy as np
from shapely.geometry import box
from branca.colormap import LinearColormap
import random
import io
import folium
from shapely.geometry import box
import geopandas as gpd
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
def wind_for_location(longitude, latitude):

    start = datetime(2015, 1, 1)
    end = datetime(2022, 12, 31)

    # Create Point for Vancouver, BC
    city = Point(latitude, longitude, 70)

    # Get daily data for 2018
    data = Monthly(city, start, end)
    data = data.fetch()

    windspeed = data['wspd']
    max_windspeed = windspeed.mean()
    return max_windspeed

def weather_for_location(longitude, latitude):

    start = datetime(2015, 1, 1)
    end = datetime(2022, 12, 31)

    # Create Point for Vancouver, BC
    city = Point(latitude, longitude, 70)

    # Get daily data for 2018
    data = Monthly(city, start, end)
    data = data.fetch()
    return data
def price_per_wind_power_plant(longitude):
    return 500_000*abs((49-longitude))/47 + 50_000
import ast
def setup_wind_farm_cluster(num_of_plants,num_my_turbines=6,num_e126_turbines=6,location=(8,50)):
    # Configure logging
    logging.basicConfig(level=logging.DEBUG)
    if isinstance(location, str):
        location = ast.literal_eval(location)
    # Get weather data
    latitude = float(location[1])
    longitude = float(location[0])
    data = weather_for_location(longitude, latitude)
    # Assuming 'data' is a DataFrame with columns ['tavg', 'wspd', 'pres']
    data["roughness_length"] = 0.15
    data["temperature"] = data["tavg"]
    data["wind_speed"] = data["wspd"]
    data["pressure"] = data["pres"]

    # Create a multiindex
    multiindex = pd.MultiIndex.from_tuples(
        [('pressure', 0), 
        ('temperature', 2), 
        ('wind_speed', 2), 
        ('roughness_length', 0), 
        ('temperature', 10), 
        ('wind_speed', 10)],
        names=['variable_name', 'height']
    )

    # Data for the multiindex DataFrame
    data_WEATHER = {
        ('pressure', 0): data["pressure"]*10,
        ('temperature', 2): data["temperature"]*10,
        ('wind_speed', 2): data["wind_speed"],
        ('roughness_length', 0): [0.15] * len(data),  # Assuming constant value for all rows
        ('temperature', 10): data["temperature"]*10,  # Assuming same temperature values for height 10
        ('wind_speed', 10): data["wind_speed"]  # Assuming same wind speed values for height 10
    }

    # Creating the MultiIndex DataFrame
    df_multi = pd.DataFrame(data_WEATHER, index=data.index)
    df_multi.ffill(inplace=True)
    df_multi.bfill(inplace=True)
    df_multi.dropna(inplace=True)
    # Initialize wind turbines
    my_turbine, e126, _ = mc_e.initialize_wind_turbines()


    # Initialize WindFarm objects
    farms = []
    num_of_plants = int(num_of_plants)
    num_my_turbines = int(num_my_turbines)
    num_e126_turbines = int(num_e126_turbines)

    
    for i in range(num_of_plants):
        farm_data = {
            'name': f'example_farm_{i}',
            'wind_turbine_fleet': [my_turbine.to_group(num_my_turbines), e126.to_group(num_e126_turbines)],
            'efficiency': 0.9
        }
        farms.append(WindFarm(**farm_data))

    # Initialize WindTurbineCluster
    example_cluster = WindTurbineCluster(name='example_cluster', wind_farms=farms)

    # Calculate power output for each farm and for the turbine cluster
    for farm in farms:
        mc_farm = TurbineClusterModelChain(farm).run_model(df_multi)
        farm.power_output = mc_farm.power_output
        farm.efficiency = 0.9  # Set efficiency

    # Calculate power output for turbine_cluster with custom modelchain data
    modelchain_data = {
        'wake_losses_model': 'wind_farm_efficiency',
        'smoothing': True,
        'block_width': 0.5,
        'standard_deviation_method': 'Staffell_Pfenninger',
        'smoothing_order': 'wind_farm_power_curves',
        'wind_speed_model': 'logarithmic',
        'density_model': 'ideal_gas',
        'temperature_model': 'linear_gradient',
        'power_output_model': 'power_curve',
        'density_correction': True,
        'obstacle_height': 0,
        'hellman_exp': None
    }
    mc_example_cluster = TurbineClusterModelChain(example_cluster, **modelchain_data).run_model(df_multi)
    example_cluster.power_output = mc_example_cluster.power_output
    # try to import matplotlib
    logging.getLogger().setLevel(logging.WARNING)
    from matplotlib import pyplot as plt
    df = example_cluster.power_output
    #make seriesto dataframe
    df = df.to_frame()
    df["Time"] = df.index
    df["example_cluster"] = df[df.columns[0]]

    #rename column
    # Plotting Function
    plt.figure(figsize=(6,4))
    plt.plot(df["Time"], df['example_cluster'], label='example_cluster')
    plt.xlabel('Time')
    plt.ylabel('Forecasted Power Output in W based on historical weather data')
    fig_1 = plt.gcf()
    plt.figure(figsize=(6,4))
    example_cluster.power_curve.plot(
        x='wind_speed', y='value', style='*')
    plt.title('Power Curve of chosen Plant in regards to wind speed')
    plt.xlabel('Wind speed in m/s')
    plt.ylabel('Power in W')
    fig_2 = plt.gcf()

    #plot the historical weather data
    plt.figure(figsize=(6,4))
    plt.plot(data["tavg"], label='Temperature')
    plt.plot(data["wspd"], label='Wind Speed')
    plt.plot(data["pres"]*0.01, label='Pressure/100')
    plt.title('Historical Weather Data used for Forecasting')
    plt.xlabel('Time')
    plt.ylabel('Historical Weather Data')
    plt.legend()
    fig_3 = plt.gcf()

    return fig_1, fig_2, fig_3, example_cluster



# Your existing code to generate the map
def generate_germany_wind_map(chosen_location_long, chosen_location_lat):
  

    # Load the map of Germany
    germany_map = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')).query('name == "Germany"')

    # Getting Germany's boundaries
    minx, miny, maxx, maxy = germany_map.total_bounds

    # Dividing Germany into a grid of 10x10
    num_squares_side = 20
    x_step = (maxx - minx) / num_squares_side
    y_step = (maxy - miny) / num_squares_side

    # Create a DataFrame to hold square polygons and their colors
    if 1==1:
        
        squares_df = pd.DataFrame(columns=['geometry', 'color'])

        # Create the squares and assign random colors
        for i in range(num_squares_side):
            for j in range(num_squares_side):
                square = box(minx + i * x_step, miny + j * y_step, minx + (i+1) * x_step, miny + (j+1) * y_step)
                # Check if the square intersects with Germany's boundary
                if germany_map.intersects(square).any():
                    squares_df = squares_df.append({'geometry': square, 'color': np.random.randint(0, 100)}, ignore_index=True)
        squares_df["center"] = 0
        squares_df["longitude"] = 0
        squares_df["latitude"] = 0
        squares_df["windspeed"] = 0
        for i in tqdm(range(len(squares_df))):
            squares_df["center"][i] = squares_df["geometry"][i].centroid
            squares_df["longitude"][i] = squares_df["center"][i].x
            squares_df["latitude"][i] = squares_df["center"][i].y
            squares_df["windspeed"][i] = wind_for_location(squares_df["longitude"][i], squares_df["latitude"][i])
        #make color the 
        squares_df["color"] =squares_df["windspeed"].copy()
        #standardize the color based on standard deviation
        #squares_df["color"] = (squares_df["color"] - squares_df["color"].mean())/squares_df["color"].std()


        squares_df.ffill(inplace=True)
        squares_df["color"] = squares_df["color"]


    # Convert squares DataFrame to GeoDataFrame
    squares_gdf = gpd.GeoDataFrame(squares_df, geometry='geometry')

    # Create a Folium map centered on Germany
    m = folium.Map(location=[(maxy + miny) / 2, (maxx + minx) / 2], zoom_start=6,tiles='cartodbpositron')

    # Add Germany's borders to the map
    folium.GeoJson(germany_map['geometry'], style_function=lambda feature: {
        'fillColor': '#ffff00',
        'color': '#000000',
        'weight': 1,
        'fillOpacity': 0,
    }).add_to(m)

    #add 

    from branca.colormap import LinearColormap

    from branca.colormap import LinearColormap
    import matplotlib



        
    from branca.colormap import LinearColormap

    # Define your colormap
    colormap = LinearColormap(['#f7fbff', '#08306b'], vmin=7, vmax=20, caption="Mean Wind speed [m/s]]")
    m.add_child(colormap)


    # Add each square to the map with a color
    for _, row in squares_gdf.iterrows():
        # Normalize color value within the range of your colormap
        #normalized_color = normalize(row['color'], vmin=5, vmax=50)

        # Get color from colormap
        color = colormap(row['color'])

        folium.GeoJson(row['geometry'], style_function=lambda feature, color=color: {
            'fillColor': color,
            'color': color,
            'weight': 1,
            'fillOpacity': 0.5,
        }).add_to(m)
    #get a random point from germany_map.geometry[121]
    #add 100 random points with price per wind power plant
    import random
    from shapely.geometry import Polygon
    import  shapely
    polygon = Polygon(germany_map.geometry[121])
    def generate_random_points(polygon, num_points):
        points = []
        min_x, min_y, max_x, max_y = polygon.bounds
        while len(points) < num_points:
            random_point = shapely.geometry.Point(random.uniform(min_x, max_x), random.uniform(min_y, max_y))
            if polygon.contains(random_point):
                points.append(random_point)
        return points

    points = generate_random_points(polygon, 100)

    # Define your colormap, red to white
    colormap_new_prices = LinearColormap(['green', 'red'], vmin=50000, vmax=100000, caption="Price per wind power plant (Only Land) [€]")
    m.add_child(colormap_new_prices)

    for point_german in points:
        #get longitude and latitude
        lon_point = point_german.x
        lat_point = point_german.y
        #get the price per wind power plant
        price = price_per_wind_power_plant(lat_point)
        #colorize the point based on the price
        color = colormap_new_prices(price)
        #add the point to the map
        folium.CircleMarker(location=[lat_point, lon_point], radius=5, color=color, fill=True,popup=price).add_to(m)
        #add the price to the map
        #add the wind speed to the map
    #get the closest point to the chosen location
    from shapely.ops import nearest_points
    #create a point
    point = shapely.geometry.Point(chosen_location_long, chosen_location_lat)
    #get the closest point
    nearest_geoms = nearest_points(point, germany_map.geometry[121])
    #get the closest point
    nearest_point = nearest_geoms[1]
    #get longitude and latitude
    lon_point = nearest_point.x
    lat_point = nearest_point.y
    #add as big marker
    folium.CircleMarker(location=[lat_point, lon_point], radius=10, color="blue", fill=True,popup="Chosen Location").add_to(m)



    return m._repr_html_(), lon_point, lat_point

import json
from llamaapi import LlamaAPI



def generate_all(str_user_query):
    # Initialize the llamaapi with your api_token
    llama = LlamaAPI("LL-19li1nMIQLwltTkGRrN9vrfGgPAPZt2VKkW9rhWGt2lD6nDl6xrnPfEQ3C1X3UpO")

    # Define your API request
    api_request_json_select_wind_power_output = {
        "messages": [
            {"role": "user", "content": f"I want to build a windfarm with 25 Wind Power turbines in nothern Germany?"},
        ],
        "functions": [
            {
                "name": "get_wind_power_estimation",
                "description": "Get the a simulation of the wind power output for a wind power plant",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "number_power_plants": {
                            "type": "number",
                            "description": "How many power plants do you want to build?",
                        },
                        "num_my_turbine_per_plant": {
                            "type": "number",
                            "description": "How many of tubine my_turbine do you want to build per plant? Default six.",
                        },
                        "num_e126_turbine_per_plant": {
                            "type": "number",
                            "description": "How many of tubine e126 do you want to build per plant? Default six.",
                        },
                        "latitude": {
                            "type": "number",
                            "description": "The longitude of the location of the wind power plant",
                        },
                        "longitude": {
                            "type": "number",
                            "description": "The longitude of the location of the wind power plant",
                        },
                    },
                },
                "required": ["number_power_plants", "num_my_turbine_per_plant", "num_e126_turbine_per_plant", "latitude", "longitude"],
            }
        ],
        "stream": False,
        "function_call": "get_wind_power_estimation",
    }

    # Make your request and handle the response
    response = llama.run(api_request_json_select_wind_power_output)
    output_llama = json.dumps(response.json(), indent=2)
    dict_llama = dict(response.json())
    dict_function = dict_llama["choices"][0]["message"]["function_call"]["arguments"]
    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"]))
    html_1, lon_point, lat_point = generate_germany_wind_map(dict_function["longitude"],dict_function["latitude"])

    int_output = int(cluster.power_curve["value"].mean())
    #generate a text output
    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."
    return text_output, html_1, fig_1, fig_2, fig_3
# Create the Gradio interface
iface = gr.Interface(
    fn=generate_all, 
    inputs=["text"],  # Input is a text box
    outputs=["text",gr.HTML(), "plot", "plot", "plot"],  # Output is HTML
    title="Wind Power Plant Location Finder",
    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."
)


if __name__ == "__main__":
    iface.launch(share=True)