Skip to content

Commit 7d71828

Browse files
0.28.3 kuhn
1 parent 4998d0b commit 7d71828

5 files changed

Lines changed: 1193 additions & 249 deletions

File tree

notebooks/00_spotPython_tests.ipynb

Lines changed: 228 additions & 155 deletions
Large diffs are not rendered by default.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
77

88
[project]
99
name = "spotpython"
10-
version = "0.28.2"
10+
version = "0.28.3"
1111
authors = [
1212
{ name="T. Bartz-Beielstein", email="tbb@bartzundbartz.de" }
1313
]

src/spotpython/plot/contour.py

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import matplotlib.pyplot as plt
22
import numpy as np
33
import os
4+
import pandas as pd
5+
from matplotlib import gridspec
46

57

68
def simple_contour(
@@ -513,3 +515,207 @@ def plotCombinations(
513515
)
514516

515517
return None
518+
519+
520+
def create_contour_plot(data, x_col, y_col, z_col, facet_col=None, aspect=1, as_table=True, figsize=(3, 3), levels=5, cmap="viridis"):
521+
"""
522+
Creates contour plots similar to R's contourplot function using matplotlib.
523+
524+
Args:
525+
data (pd.DataFrame): The DataFrame containing the data.
526+
x_col (str): The name of the column to use for the x-axis.
527+
y_col (str): The name of the column to use for the y-axis.
528+
z_col (str): The name of the column to use for the z-axis (contour values).
529+
facet_col (str, optional): The name of the column to use for faceting (creating subplots). Defaults to None.
530+
aspect (float, optional): The aspect ratio of the plot. Defaults to 1.
531+
as_table (bool, optional): Whether to arrange facets as a table. Defaults to True.
532+
figsize (tuple, optional): The size of the figure. Defaults to (3, 3).
533+
levels (int, optional): The number of contour levels. Defaults to 5.
534+
cmap (str, optional): The colormap to use. Defaults to "viridis".
535+
536+
Returns:
537+
None: Displays the contour plot(s).
538+
539+
Raises:
540+
ValueError: If the specified columns are not found in the DataFrame.
541+
542+
Examples:
543+
>>> from spotpython.plot.contour import create_contour_plot
544+
import numpy as np
545+
import pandas as pd
546+
# Create a grid of x and y values
547+
x = np.linspace(-5, 5, 100)
548+
y = np.linspace(-5, 5, 100)
549+
x_grid, y_grid = np.meshgrid(x, y)
550+
# Calculate z = x^2 + y^2
551+
z = x_grid**2 + y_grid**2
552+
# Flatten the grid and create a DataFrame
553+
data = pd.DataFrame({
554+
'x': x_grid.flatten(),
555+
'y': y_grid.flatten(),
556+
'z': z.flatten()
557+
})
558+
# Create the contour plot
559+
create_contour_plot(data, 'x', 'y', 'z', facet_col=None)
560+
>>> # Create a contour plot with faceting
561+
from spotpython.plot.contour import create_contour_plot
562+
import numpy as np
563+
import pandas as pd
564+
# Create a grid of x and y values
565+
x = np.linspace(-5, 5, 50)
566+
y = np.linspace(-5, 5, 50)
567+
x_grid, y_grid = np.meshgrid(x, y)
568+
# Calculate z = x^2 + y^2 for two different facets
569+
z1 = x_grid**2 + y_grid**2
570+
z2 = (x_grid - 2)**2 + (y_grid - 2)**2
571+
# Flatten the grids and create a DataFrame
572+
data = pd.DataFrame({
573+
'x': np.tile(x, len(y) * 2), # Repeat x values for both facets
574+
'y': np.repeat(y, len(x) * 2), # Repeat y values for both facets
575+
'z': np.concatenate([z1.flatten(), z2.flatten()]), # Combine z values for both facets
576+
'facet': ['Facet A'] * len(z1.flatten()) + ['Facet B'] * len(z2.flatten()) # Create facet column
577+
})
578+
# Create the contour plot with facets
579+
create_contour_plot(data, 'x', 'y', 'z', facet_col='facet')
580+
"""
581+
582+
if facet_col:
583+
facet_values = data[facet_col].unique()
584+
num_facets = len(facet_values)
585+
586+
# Determine subplot layout
587+
if as_table:
588+
num_cols = int(np.ceil(np.sqrt(num_facets)))
589+
num_rows = int(np.ceil(num_facets / num_cols))
590+
else:
591+
num_cols = num_facets
592+
num_rows = 1
593+
594+
fig, axes = plt.subplots(num_rows, num_cols, figsize=(figsize[0] * num_cols, figsize[1] * num_rows))
595+
axes = np.array(axes).flatten() # Flatten the axes array for easy indexing
596+
597+
for i, facet_value in enumerate(facet_values):
598+
ax = axes[i]
599+
facet_data = data[data[facet_col] == facet_value]
600+
601+
# Create grid for contour plot
602+
x = np.unique(facet_data[x_col])
603+
y = np.unique(facet_data[y_col])
604+
X, Y = np.meshgrid(x, y)
605+
Z = facet_data.pivot_table(index=y_col, columns=x_col, values=z_col).values
606+
607+
# Plot contour
608+
contour = ax.contour(X, Y, Z, levels=levels, cmap=cmap) # Adjust levels and cmap as needed
609+
ax.clabel(contour, inline=True, fontsize=8)
610+
611+
# Set labels and title
612+
ax.set_xlabel(x_col)
613+
ax.set_ylabel(y_col)
614+
ax.set_title(f"{facet_col} = {np.round(facet_value,2)}")
615+
ax.set_aspect(aspect)
616+
617+
# Remove empty subplots
618+
for i in range(num_facets, len(axes)):
619+
fig.delaxes(axes[i])
620+
621+
fig.tight_layout()
622+
plt.show()
623+
624+
else:
625+
# Create grid for contour plot
626+
x = np.unique(data[x_col])
627+
y = np.unique(data[y_col])
628+
X, Y = np.meshgrid(x, y)
629+
Z = data.pivot_table(index=y_col, columns=x_col, values=z_col).values
630+
631+
# Plot contour
632+
fig, ax = plt.subplots(figsize=figsize)
633+
contour = ax.contour(X, Y, Z, levels=10, cmap="viridis") # Adjust levels and cmap as needed
634+
ax.clabel(contour, inline=True, fontsize=8)
635+
636+
# Set labels and title
637+
ax.set_xlabel(x_col)
638+
ax.set_ylabel(y_col)
639+
ax.set_title(f"Contour Plot of {z_col}")
640+
ax.set_aspect(aspect)
641+
642+
plt.show()
643+
644+
645+
def mo_generate_plot_grid(variables, resolutions, functions):
646+
"""
647+
Generate a grid of input variables and apply objective functions.
648+
649+
Args:
650+
variables (dict): A dictionary where keys are variable names (e.g., "time", "temperature")
651+
and values are tuples of (min_value, max_value).
652+
resolutions (dict): A dictionary where keys are variable names and values are the number of points.
653+
functions (dict): A dictionary where keys are function names and values are callable functions.
654+
655+
Returns:
656+
pd.DataFrame: A DataFrame containing the grid and the results of the objective functions.
657+
"""
658+
# Create a meshgrid for all variables
659+
grids = [np.linspace(variables[var][0], variables[var][1], resolutions[var]) for var in variables]
660+
grid = np.array(np.meshgrid(*grids)).T.reshape(-1, len(variables))
661+
662+
# Create a DataFrame for the grid
663+
plot_grid = pd.DataFrame(grid, columns=variables.keys())
664+
665+
# Apply each function to the grid
666+
for func_name, func in functions.items():
667+
plot_grid[func_name] = plot_grid.apply(lambda row: func(row.values), axis=1)
668+
669+
return plot_grid
670+
671+
672+
def mo_create_contour_plots(plot_grid, x_col, y_col, z_col, facet_col, z_label="Objective", cmap="viridis", levels=10):
673+
"""
674+
Create contour plots for a given grid of data.
675+
676+
Args:
677+
plot_grid (pd.DataFrame): The data containing the grid and objective values.
678+
x_col (str): The column name for the x-axis.
679+
y_col (str): The column name for the y-axis.
680+
z_col (str): The column name for the z-axis (objective values).
681+
facet_col (str): The column name for the facet (e.g., temperature).
682+
z_label (str): Label for the colorbar.
683+
cmap (str): Colormap for the contour plot.
684+
levels (int): Number of contour levels.
685+
"""
686+
unique_facets = plot_grid[facet_col].unique()
687+
n_facets = len(unique_facets)
688+
689+
# Set up a grid of subplots
690+
n_cols = 2
691+
n_rows = (n_facets + 1) // n_cols
692+
fig = plt.figure(figsize=(12, 5 * n_rows))
693+
gs = gridspec.GridSpec(n_rows, n_cols + 1, width_ratios=[1] * n_cols + [0.05]) # Add space for colorbar
694+
695+
axes = [fig.add_subplot(gs[i // n_cols, i % n_cols]) for i in range(n_facets)]
696+
697+
for i, facet in enumerate(unique_facets):
698+
# Filter data for the current facet
699+
facet_data = plot_grid[plot_grid[facet_col] == facet]
700+
701+
# Pivot the data for contour plotting
702+
pivot_table = facet_data.pivot(index=y_col, columns=x_col, values=z_col)
703+
704+
# Create the contour plot
705+
ax = axes[i]
706+
contour = ax.contourf(pivot_table.columns, pivot_table.index, pivot_table.values, cmap=cmap, levels=levels) # x-axis # y-axis # z-axis
707+
contour_lines = ax.contour(pivot_table.columns, pivot_table.index, pivot_table.values, colors="black", linewidths=0.5, levels=levels)
708+
ax.clabel(contour_lines, inline=True, fontsize=8) # Add labels to contour lines
709+
710+
# Set plot labels and title
711+
ax.set_title(f"{facet_col} = {facet:.2f}")
712+
ax.set_xlabel(x_col)
713+
ax.set_ylabel(y_col)
714+
715+
# Add a colorbar to the right of the plots
716+
cbar_ax = fig.add_subplot(gs[:, -1]) # Use the last column for the colorbar
717+
fig.colorbar(contour, cax=cbar_ax, orientation="vertical", label=z_label)
718+
719+
# Adjust layout and show the plot
720+
plt.tight_layout()
721+
plt.show()

0 commit comments

Comments
 (0)