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)