@@ -517,7 +517,7 @@ def plotCombinations(
517517 return None
518518
519519
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" ):
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" ) -> None :
521521 """
522522 Creates contour plots similar to R's contourplot function using matplotlib.
523523
@@ -611,7 +611,7 @@ def create_contour_plot(data, x_col, y_col, z_col, facet_col=None, aspect=1, as_
611611 # Set labels and title
612612 ax .set_xlabel (x_col )
613613 ax .set_ylabel (y_col )
614- ax .set_title (f"{ facet_col } = { np .round (facet_value ,2 )} " )
614+ ax .set_title (f"{ facet_col } = { np .round (facet_value , 2 )} " )
615615 ax .set_aspect (aspect )
616616
617617 # Remove empty subplots
@@ -630,7 +630,7 @@ def create_contour_plot(data, x_col, y_col, z_col, facet_col=None, aspect=1, as_
630630
631631 # Plot contour
632632 fig , ax = plt .subplots (figsize = figsize )
633- contour = ax .contour (X , Y , Z , levels = 10 , cmap = "viridis" ) # Adjust levels and cmap as needed
633+ contour = ax .contour (X , Y , Z , levels = levels , cmap = "viridis" ) # Adjust levels and cmap as needed
634634 ax .clabel (contour , inline = True , fontsize = 8 )
635635
636636 # Set labels and title
@@ -642,7 +642,7 @@ def create_contour_plot(data, x_col, y_col, z_col, facet_col=None, aspect=1, as_
642642 plt .show ()
643643
644644
645- def mo_generate_plot_grid (variables , resolutions , functions ):
645+ def mo_generate_plot_grid (variables , resolutions , functions ) -> pd . DataFrame :
646646 """
647647 Generate a grid of input variables and apply objective functions.
648648
@@ -669,53 +669,277 @@ def mo_generate_plot_grid(variables, resolutions, functions):
669669 return plot_grid
670670
671671
672- def mo_create_contour_plots (plot_grid , x_col , y_col , z_col , facet_col , z_label = "Objective" , cmap = "viridis" , levels = 10 ):
672+ def contour_plot (
673+ data ,
674+ x_col ,
675+ y_col ,
676+ z_col ,
677+ facet_col = None ,
678+ aspect = 1 ,
679+ as_table = True ,
680+ figsize = (4 , 4 ),
681+ levels = 10 ,
682+ cmap = "viridis" ,
683+ highlight_point = None ,
684+ highlight_color = "red" ,
685+ highlight_size = 50 ,
686+ highlight_label = None ,
687+ highlight_legend_loc = "upper right" ,
688+ highlight_legend_fontsize = 8 ,
689+ ) -> None :
690+ """
691+ Creates contour plots (single or faceted) using matplotlib.
692+
693+ Args:
694+ data (pd.DataFrame): The DataFrame containing the data.
695+ x_col (str): The name of the column to use for the x-axis.
696+ y_col (str): The name of the column to use for the y-axis.
697+ z_col (str): The name of the column to use for the z-axis (contour values).
698+ facet_col (str, optional): The name of the column to use for faceting (creating subplots). Defaults to None.
699+ aspect (float, optional): The aspect ratio of the plot. Defaults to 1.
700+ as_table (bool, optional): Whether to arrange facets as a table. Defaults to True.
701+ figsize (tuple, optional): The size of the figure. Defaults to (4, 4).
702+ levels (int, optional): The number of contour levels. Defaults to 5.
703+ cmap (str, optional): The colormap to use. Defaults to "viridis".
704+ highlight_point (np.array, optional): A 1-dimensional array specifying a single point [x, y] to highlight. Defaults to None.
705+ highlight_color (str, optional): Color for the highlighted point. Defaults to "red".
706+ highlight_size (int, optional): Size of the highlighted point. Defaults to 50.
707+ highlight_label (str, optional): Label for the highlighted point. Defaults to "Highlighted Point".
708+ highlight_legend_loc (str, optional): Location for the legend. Defaults to "upper right".
709+ highlight_legend_fontsize (int, optional): Font size for the legend. Defaults to 8.
710+
711+ Returns:
712+ None: Displays the contour plot(s).
713+ """
714+ if facet_col :
715+ facet_values = data [facet_col ].unique ()
716+ num_facets = len (facet_values )
717+
718+ # Determine subplot layout
719+ if as_table :
720+ num_cols = int (np .ceil (np .sqrt (num_facets )))
721+ num_rows = int (np .ceil (num_facets / num_cols ))
722+ else :
723+ num_cols = num_facets
724+ num_rows = 1
725+
726+ fig , axes = plt .subplots (num_rows , num_cols , figsize = (figsize [0 ] * num_cols , figsize [1 ] * num_rows ))
727+ axes = np .array (axes ).flatten () # Flatten the axes array for easy indexing
728+
729+ for i , facet_value in enumerate (facet_values ):
730+ ax = axes [i ]
731+ facet_data = data [data [facet_col ] == facet_value ]
732+
733+ # Create grid for contour plot
734+ x = np .unique (facet_data [x_col ])
735+ y = np .unique (facet_data [y_col ])
736+ X , Y = np .meshgrid (x , y )
737+ Z = facet_data .pivot_table (index = y_col , columns = x_col , values = z_col ).values
738+
739+ # Plot contour
740+ contour = ax .contour (X , Y , Z , levels = levels , cmap = cmap )
741+ ax .clabel (contour , inline = True , fontsize = 8 )
742+
743+ # Highlight the specified point
744+ if highlight_point is not None :
745+ ax .scatter (highlight_point [0 ], highlight_point [1 ], color = highlight_color , s = highlight_size , label = highlight_label , zorder = 10 )
746+ if highlight_label :
747+ ax .legend (loc = highlight_legend_loc , fontsize = highlight_legend_fontsize )
748+
749+ # Set labels and title
750+ ax .set_xlabel (x_col )
751+ ax .set_ylabel (y_col )
752+ ax .set_title (f"{ facet_col } = { np .round (facet_value , 2 )} " )
753+ ax .set_aspect (aspect )
754+
755+ # Remove empty subplots
756+ for i in range (num_facets , len (axes )):
757+ fig .delaxes (axes [i ])
758+
759+ fig .tight_layout ()
760+ plt .show ()
761+
762+ else :
763+ # Create grid for contour plot
764+ x = np .unique (data [x_col ])
765+ y = np .unique (data [y_col ])
766+ X , Y = np .meshgrid (x , y )
767+ Z = data .pivot_table (index = y_col , columns = x_col , values = z_col ).values
768+
769+ # Plot contour
770+ fig , ax = plt .subplots (figsize = figsize )
771+ contour = ax .contour (X , Y , Z , levels = levels , cmap = cmap )
772+ ax .clabel (contour , inline = True , fontsize = 8 )
773+
774+ # Highlight the specified point
775+ if highlight_point is not None :
776+ ax .scatter (highlight_point [0 ], highlight_point [1 ], color = highlight_color , s = highlight_size , label = highlight_label , zorder = 10 )
777+ if highlight_label :
778+ ax .legend (loc = highlight_legend_loc , fontsize = highlight_legend_fontsize )
779+
780+ # Set labels and title
781+ ax .set_xlabel (x_col )
782+ ax .set_ylabel (y_col )
783+ ax .set_title (f"Contour Plot of { z_col } " )
784+ ax .set_aspect (aspect )
785+
786+ plt .show ()
787+
788+
789+ def contourf_plot (
790+ data ,
791+ x_col ,
792+ y_col ,
793+ z_col ,
794+ facet_col = None ,
795+ aspect = 1 ,
796+ as_table = True ,
797+ figsize = (4 , 4 ),
798+ levels = 10 ,
799+ cmap = "viridis" ,
800+ show_contour_lines = True ,
801+ contour_line_color = "black" ,
802+ contour_line_width = 0.5 ,
803+ colorbar_orientation = "vertical" ,
804+ wspace = 0.4 ,
805+ hspace = 0.4 ,
806+ highlight_point = None , # New argument to specify a single point to highlight
807+ highlight_color = "red" , # Color for the highlighted point
808+ highlight_size = 50 , # Size of the highlighted point
809+ highlight_label = None , # Label for the highlighted point
810+ highlight_legend_loc = "upper right" , # Legend location
811+ highlight_legend_fontsize = 8 , # Font size for the legend
812+ ) -> None :
673813 """
674- Create contour plots for a given grid of data .
814+ Creates filled contour plots (single or faceted) using matplotlib .
675815
676816 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.
817+ data (pd.DataFrame): The DataFrame containing the data.
818+ x_col (str): The name of the column to use for the x-axis.
819+ y_col (str): The name of the column to use for the y-axis.
820+ z_col (str): The name of the column to use for the z-axis (contour values).
821+ facet_col (str, optional): The name of the column to use for faceting (creating subplots). Defaults to None.
822+ aspect (float, optional): The aspect ratio of the plot. Defaults to 1.
823+ as_table (bool, optional): Whether to arrange facets as a table. Defaults to True.
824+ figsize (tuple, optional): The size of the figure. Defaults to (4, 4).
825+ levels (int, optional): The number of contour levels. Defaults to 10.
826+ cmap (str, optional): The colormap to use. Defaults to "viridis".
827+ show_contour_lines (bool, optional): Whether to overlay contour lines on the filled plot. Defaults to False.
828+ contour_line_color (str, optional): Color of the contour lines. Defaults to "black".
829+ contour_line_width (float, optional): Width of the contour lines. Defaults to 0.5.
830+ colorbar_orientation (str, optional): Orientation of the colorbar ("vertical" or "horizontal"). Defaults to "vertical".
831+ wspace (float, optional): Horizontal spacing between subplots. Defaults to 0.4.
832+ hspace (float, optional): Vertical spacing between subplots. Defaults to 0.4.
833+ highlight_point (np.array, optional): A 1-dimensional array specifying a single point [x, y] to highlight. Defaults to None.
834+ highlight_color (str, optional): Color for the highlighted point. Defaults to "red".
835+ highlight_size (int, optional): Size of the highlighted point. Defaults to 50.
836+ highlight_label (str, optional): Label for the highlighted point. Defaults to None.
837+ highlight_legend_loc (str, optional): Location for the legend. Defaults to "upper right".
838+ highlight_legend_fontsize (int, optional): Font size for the legend. Defaults to 8.
839+
840+ Returns:
841+ None: Displays the filled contour plot(s).
685842 """
686- unique_facets = plot_grid [facet_col ].unique ()
687- n_facets = len (unique_facets )
843+ if facet_col :
844+ facet_values = data [facet_col ].unique ()
845+ num_facets = len (facet_values )
688846
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
847+ # Determine subplot layout
848+ if as_table :
849+ num_cols = int (np .ceil (np .sqrt (num_facets )))
850+ num_rows = int (np .ceil (num_facets / num_cols ))
851+ else :
852+ num_cols = num_facets
853+ num_rows = 1
694854
695- axes = [fig .add_subplot (gs [i // n_cols , i % n_cols ]) for i in range (n_facets )]
855+ # Create figure with gridspec for colorbar placement
856+ if colorbar_orientation == "vertical" :
857+ fig = plt .figure (figsize = (figsize [0 ] * num_cols , figsize [1 ] * num_rows ))
858+ spec = gridspec .GridSpec (num_rows , num_cols + 1 , width_ratios = [1 ] * num_cols + [0.05 ], wspace = wspace , hspace = hspace )
859+ else : # Horizontal colorbar
860+ fig = plt .figure (figsize = (figsize [0 ] * num_cols , figsize [1 ] * num_rows + 1 ))
861+ spec = gridspec .GridSpec (num_rows + 1 , num_cols , height_ratios = [1 ] * num_rows + [0.05 ], wspace = wspace , hspace = hspace )
696862
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 ]
863+ axes = []
864+ for row in range (num_rows ):
865+ for col in range (num_cols ):
866+ if row * num_cols + col < num_facets :
867+ axes .append (fig .add_subplot (spec [row , col ]))
700868
701- # Pivot the data for contour plotting
702- pivot_table = facet_data .pivot (index = y_col , columns = x_col , values = z_col )
869+ for i , facet_value in enumerate (facet_values ):
870+ ax = axes [i ]
871+ facet_data = data [data [facet_col ] == facet_value ]
872+
873+ # Create grid for contour plot
874+ x = np .unique (facet_data [x_col ])
875+ y = np .unique (facet_data [y_col ])
876+ X , Y = np .meshgrid (x , y )
877+ Z = facet_data .pivot_table (index = y_col , columns = x_col , values = z_col ).values
878+
879+ # Plot filled contour
880+ contour = ax .contourf (X , Y , Z , levels = levels , cmap = cmap )
881+
882+ # Optionally overlay contour lines
883+ if show_contour_lines :
884+ contour_lines = ax .contour (X , Y , Z , levels = levels , colors = contour_line_color , linewidths = contour_line_width )
885+ ax .clabel (contour_lines , inline = True , fontsize = 8 )
886+
887+ # Highlight the specified point
888+ if highlight_point is not None :
889+ ax .scatter (highlight_point [0 ], highlight_point [1 ], color = highlight_color , s = highlight_size , label = highlight_label , zorder = 10 )
890+ if highlight_label :
891+ ax .legend (loc = highlight_legend_loc , fontsize = highlight_legend_fontsize )
892+
893+ # Set labels and title
894+ ax .set_xlabel (x_col )
895+ ax .set_ylabel (y_col )
896+ ax .set_title (f"{ facet_col } = { np .round (facet_value , 2 )} " )
897+ ax .set_aspect (aspect )
898+
899+ # Add colorbar
900+ if colorbar_orientation == "vertical" :
901+ cbar_ax = fig .add_subplot (spec [:, - 1 ]) # Last column for vertical colorbar
902+ else :
903+ cbar_ax = fig .add_subplot (spec [- 1 , :]) # Last row for horizontal colorbar
904+ fig .colorbar (contour , cax = cbar_ax , orientation = colorbar_orientation , label = z_col )
703905
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
906+ plt .show ()
709907
710- # Set plot labels and title
711- ax .set_title (f"{ facet_col } = { facet :.2f} " )
908+ else :
909+ # Create grid for contour plot
910+ x = np .unique (data [x_col ])
911+ y = np .unique (data [y_col ])
912+ X , Y = np .meshgrid (x , y )
913+ Z = data .pivot_table (index = y_col , columns = x_col , values = z_col ).values
914+
915+ # Create figure
916+ fig , ax = plt .subplots (figsize = figsize )
917+
918+ # Plot filled contour
919+ contour = ax .contourf (X , Y , Z , levels = levels , cmap = cmap )
920+
921+ # Optionally overlay contour lines
922+ if show_contour_lines :
923+ contour_lines = ax .contour (X , Y , Z , levels = levels , colors = contour_line_color , linewidths = contour_line_width )
924+ ax .clabel (contour_lines , inline = True , fontsize = 8 )
925+
926+ # Highlight the specified point
927+ if highlight_point is not None :
928+ ax .scatter (highlight_point [0 ], highlight_point [1 ], color = highlight_color , s = highlight_size , label = highlight_label , zorder = 10 )
929+ if highlight_label :
930+ ax .legend (loc = highlight_legend_loc , fontsize = highlight_legend_fontsize )
931+
932+ # Set labels and title
712933 ax .set_xlabel (x_col )
713934 ax .set_ylabel (y_col )
935+ ax .set_title (f"Filled Contour Plot of { z_col } " )
936+ ax .set_aspect (aspect )
714937
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 )
938+ # Add colorbar
939+ if colorbar_orientation == "vertical" :
940+ cbar_ax = fig .add_axes ([0.92 , 0.15 , 0.02 , 0.7 ]) # Position for vertical colorbar
941+ else :
942+ cbar_ax = fig .add_axes ([0.15 , 0.05 , 0.7 , 0.02 ]) # Position for horizontal colorbar
943+ fig .colorbar (contour , cax = cbar_ax , orientation = colorbar_orientation , label = z_col )
718944
719- # Adjust layout and show the plot
720- plt .tight_layout ()
721- plt .show ()
945+ plt .show ()
0 commit comments