From abf4143ca48313b9dd13ac6b09fc045b0a1efa1f Mon Sep 17 00:00:00 2001 From: "clara.bayley" Date: Wed, 14 Jan 2026 12:27:45 +0100 Subject: [PATCH 1/4] refactor: larger fonts and save as pdfs --- scripts/plotting/prettyplots_kerneltimer.py | 107 +++++++++++++------- 1 file changed, 70 insertions(+), 37 deletions(-) diff --git a/scripts/plotting/prettyplots_kerneltimer.py b/scripts/plotting/prettyplots_kerneltimer.py index ea3b5d0..4a466a6 100644 --- a/scripts/plotting/prettyplots_kerneltimer.py +++ b/scripts/plotting/prettyplots_kerneltimer.py @@ -62,6 +62,19 @@ simulated_time = 4800 # length of simulation [s] ### -------------------------------------- ### +# %% font sizes for beautifying plots +SMALL_SIZE = 15 +MEDIUM_SIZE = 16 +BIG_SIZE = 18 + +plt.rc("font", size=SMALL_SIZE) # controls default text sizes +plt.rc("axes", titlesize=BIG_SIZE) # fontsize of the axes title +plt.rc("axes", labelsize=BIG_SIZE) # fontsize of the x and y labels +plt.rc("xtick", labelsize=MEDIUM_SIZE) # fontsize of the tick labels +plt.rc("ytick", labelsize=MEDIUM_SIZE) # fontsize of the tick labels +plt.rc("legend", fontsize=SMALL_SIZE) # legend fontsize +plt.rc("figure", titlesize=BIG_SIZE) # fontsize of the figure title + # %% ### --------- plotting functions --------- ### @@ -102,7 +115,7 @@ def plot_wallclock_vs_total_num_supers( simulated_time: float, withlines: Optional[bool] = False, ): - fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(10.5, 7), sharex=True) + fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(10.5, 8.35), sharex=True) axs = axs.flatten() # buildtype: linestyle @@ -118,27 +131,34 @@ def plot_wallclock_vs_total_num_supers( nthreads = nthreads2plot[build] ds = datasets[build].sel(nthreads=nthreads) alpha = 0.3 - + axtitle_fontsize = 16 if build == "OpenMP" or build == "C++Threads": ax.text( 0.5, - 0.93, + 1.025, f"{build} with {nthreads} Threads", ha="center", transform=ax.transAxes, - fontsize=11, + fontsize=axtitle_fontsize, ) elif build == "CUDA": ax.text( 0.5, - 0.93, + 1.025, f"{build} with 1 GPU and {nthreads} CPU Threads", ha="center", transform=ax.transAxes, - fontsize=11, + fontsize=axtitle_fontsize, ) else: - ax.text(0.5, 0.93, build, ha="center", transform=ax.transAxes, fontsize=11) + ax.text( + 0.5, + 1.025, + build, + ha="center", + transform=ax.transAxes, + fontsize=axtitle_fontsize, + ) # variable_name: [label, colour] vars = { @@ -178,19 +198,19 @@ def plot_wallclock_vs_total_num_supers( axb = axs[0].twinx() axb.set_yticks([]) axb.spines[["left", "bottom", "right", "top"]].set_visible(False) - axb.legend(handles=perf, loc="lower left") + axb.legend(handles=perf, loc=(0.015, 0.835)) ax.set_xscale("log") ax.set_yscale("log") ax.spines[["right", "top"]].set_visible(False) handles, labels = axs[2].get_legend_handles_labels() # solid lines - axs[0].legend(handles=handles, labels=labels, loc="lower right") + axs[0].legend(handles=handles, labels=labels, loc=(0.515, 0.015)) - axs[0].set_ylabel("wall-clock time per simulated second /s") - axs[2].set_ylabel("wall-clock time per simulated second /s") - axs[2].set_xlabel("total number of superdroplets in domain") - axs[3].set_xlabel("total number of superdroplets in domain") + axs[0].set_ylabel("wall-clock time per\nsimulated second /s") + axs[2].set_ylabel("wall-clock time per\nsimulated second /s") + axs[2].set_xlabel("total number of superdroplets\nin domain") + axs[3].set_xlabel("total number of superdroplets\nin domain") for ax in axs: ax.set_ylim([5e-5, 5]) @@ -314,7 +334,7 @@ def plot_wallclock_strong_scaling_for_total_num_supers( ax.set_xlim([0, 130]) ax.set_ylim([1e-4, 1e1]) ax.set_xticks([1, 16, 64, 128]) - ax.set_xlabel("number of CPU threads") + ax.set_xlabel("# CPU threads") if a != 0: ax.set_yticklabels([]) @@ -330,11 +350,18 @@ def plot_speedup_strong_scaling_for_total_num_supers( nsupers: int, colors: Optional[dict] = None, ): - fig = plt.figure(figsize=(13.3, 4.75)) - gs = GridSpec(1, 3, figure=fig) + fig = plt.figure(figsize=(11, 8.5)) + gs = GridSpec(2, 2, figure=fig) axs = [] - for i in range(3): - axs.append(fig.add_subplot(gs[0, i])) + axs.append(fig.add_subplot(gs[0, 0])) + axs.append(fig.add_subplot(gs[1, 0])) + axs.append(fig.add_subplot(gs[1, 1])) + legaxs = [fig.add_subplot(gs[0, 1])] # for legend + legaxs.append(legaxs[0].twinx()) + for lax in legaxs: + lax.spines[["left", "top", "right", "bottom"]].set_visible(False) + lax.set_xticks([]) + lax.set_yticks([]) # buildtype: line/marker style styles = { @@ -451,36 +478,42 @@ def plot_speedup_strong_scaling_for_total_num_supers( zorder=0, ) handles[build] = lines[0] - ax.spines[["right", "top"]].set_visible(False) - axs[0].legend( - handles=list(handles.values()), labels=list(handles.keys()), loc="upper left" - ) + perf = ax.plot( + [1, 128], + [1, 128], + linewidth=0.5, + linestyle=(0, (25, 10)), # loosely dashed + color="dimgrey", + label="1:1 scaling", + zorder=0, + ) + ax.spines[["right", "top"]].set_visible(False) - ax_tmp = axs[0].twinx() - ax_tmp.spines[["left", "top", "right", "top"]].set_visible(False) - ax_tmp.set_xticks([]) - ax_tmp.set_yticks([]) - labels = [formatted_labels[i] for i in handles2.keys()] - labels[0] = f"#SDs={labels[0]}" - ax_tmp.legend(handles=list(handles2.values()), labels=labels, loc="upper right") + handles1 = list(handles.values()) + [perf[0]] + labels1 = list(handles.keys()) + [perf[0].get_label()] + legaxs[0].legend(handles=handles1, labels=labels1, loc=(0.2, 0.55)) - axs[0].set_ylabel("speed-up") + labels2 = [formatted_labels[i] for i in handles2.keys()] + labels2[0] = f"# SDs = {labels2[0]}" + legaxs[1].legend(handles=list(handles2.values()), labels=labels2, loc=(0.2, 0.0)) - for a, ax in enumerate(axs): + for ax in axs: ax.set_xlim([0, 130]) ax.set_ylim([1, 130]) ax.set_xticks([1, 16, 64, 128]) ax.set_yticks([1, 32, 64, 96, 128]) - ax.set_xlabel("number of CPU threads") + ax.set_xlabel("# CPU threads") + ax.set_ylabel("speed-up") axs[2].set_ylim([0, 36]) axs[2].set_yticks([1, 16, 32]) - fig.tight_layout() + plt.subplots_adjust(hspace=0.45, wspace=0.25) return fig, axs +### -------------------------------------- ### ### -------------------------------------- ### ### -------------- plotting -------------- ### @@ -493,13 +526,13 @@ def plot_speedup_strong_scaling_for_total_num_supers( "C++Threads": 128, } fig, axs = plot_wallclock_vs_total_num_supers(datasets, nthreads2plot, simulated_time) -savename = path4plots / "wallclock_vs_totnsupers.png" +savename = path4plots / "wallclock_vs_totnsupers.pdf" save_figure(savename) fig, axs = plot_wallclock_vs_total_num_supers( datasets, nthreads2plot, simulated_time, withlines=True ) -savename = path4plots / "wallclock_vs_totnsupers_withlines.png" +savename = path4plots / "wallclock_vs_totnsupers_withlines.pdf" save_figure(savename) # %% ngbxs2plot = { @@ -514,7 +547,7 @@ def plot_speedup_strong_scaling_for_total_num_supers( simulated_time, nsupers, ) -savename = path4plots / "strong_scaling_wallclock.png" +savename = path4plots / "strong_scaling_wallclock.pdf" save_figure(savename) # %% @@ -533,7 +566,7 @@ def plot_speedup_strong_scaling_for_total_num_supers( fig, axs = plot_speedup_strong_scaling_for_total_num_supers( datasets, ngbxs2plot, nsupers, colors=colors ) -savename = path4plots / "strong_scaling_speedup.png" +savename = path4plots / "strong_scaling_speedup.pdf" save_figure(savename) ### -------------------------------------- ### From 85cd91d0b47bda18cc1a99cdaa3f59185422f866 Mon Sep 17 00:00:00 2001 From: "clara.bayley" Date: Wed, 14 Jan 2026 13:53:09 +0100 Subject: [PATCH 2/4] refactor: larger fonts and save as pdfs for memory plots --- .../plotting/prettyplots_spacetimestack.py | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/scripts/plotting/prettyplots_spacetimestack.py b/scripts/plotting/prettyplots_spacetimestack.py index d216f02..775f0c8 100644 --- a/scripts/plotting/prettyplots_spacetimestack.py +++ b/scripts/plotting/prettyplots_spacetimestack.py @@ -60,6 +60,19 @@ } ### -------------------------------------- ### +# %% font sizes for beautifying plots +SMALL_SIZE = 15 +MEDIUM_SIZE = 16 +BIG_SIZE = 18 + +plt.rc("font", size=SMALL_SIZE) # controls default text sizes +plt.rc("axes", titlesize=BIG_SIZE) # fontsize of the axes title +plt.rc("axes", labelsize=BIG_SIZE) # fontsize of the x and y labels +plt.rc("xtick", labelsize=MEDIUM_SIZE) # fontsize of the tick labels +plt.rc("ytick", labelsize=MEDIUM_SIZE) # fontsize of the tick labels +plt.rc("legend", fontsize=MEDIUM_SIZE) # legend fontsize +plt.rc("figure", titlesize=BIG_SIZE) # fontsize of the figure title + # %% ### --------- plotting functions --------- ### @@ -132,7 +145,7 @@ def plot_serial_space_time_stack_memory_allocations_vs_total_num_supers( ax0.set_xlabel("total number of superdroplets in domain / 10$^6$") ax0.set_ylabel("CPU high-water\nmemory consumption /GB", color="brown") - ax0b.set_ylabel("maximum memory allocation /GB", color="grey") + ax0b.set_ylabel("maximum memory\nallocation /GB", color="grey") ax0.set_xlim(left=0) ax0.set_ylim(bottom=0.0) ax0b.set_ylim(ax0.get_ylim()) @@ -152,7 +165,7 @@ def plot_serial_space_time_stack_memory_allocations_vs_total_num_supers( "Linear fit, m={:.3f}".format(m1.values), ] handles = [lines0[0], lines_fita[0], lines_fitb[0]] - leg = ax0.legend(labels=labels, handles=handles, loc="upper left") + leg = ax0.legend(labels=labels, handles=handles, loc=(0.01, 0.5)) plt.setp(leg.get_texts()[1], color="brown") plt.setp(leg.get_texts()[2], color="grey") @@ -165,14 +178,14 @@ def plot_space_time_stack_memory_allocations_vs_nthreads( nsupers: int, colors: Optional[dict] = None, ): - fig = plt.figure(figsize=(11, 7)) + fig = plt.figure(figsize=(11, 11)) gs = GridSpec( 2, 3, figure=fig, height_ratios=[1, 1], width_ratios=[8, 8, 1], - wspace=0.4, + wspace=0.6, hspace=0.4, ) ax0 = fig.add_subplot(gs[0, :]) @@ -286,27 +299,22 @@ def plot_space_time_stack_memory_allocations_vs_nthreads( handles2[build] = lines_lab[0] ax1.set_xlim([0, 130]) - ax1.set_xlabel("number of CPU threads") + ax1.set_xlabel("# CPU threads") ax1.set_ylabel( "CPU high-water memory\nconsumption relative to serial", color="brown" ) ax2.set_xlim([0, 130]) - ax2.set_xlabel("number of CPU threads") + ax2.set_xlabel("# CPU threads") ax2.set_ylabel("maximum memory\nallocation relative to serial", color="grey") legax1.legend( - handles=list(handles2.values()), - labels=list(handles2.keys()), - loc="upper center", - fontsize=9, + handles=list(handles2.values()), labels=list(handles2.keys()), loc=(-2.5, 0.5) ) labels = [formatted_labels[i] for i in handles1.keys()] - labels[0] = f"#SDs = {labels[0]}" - legax2.legend( - handles=list(handles1.values()), labels=labels, loc=(-1.25, 0.15), fontsize=9 - ) + labels[0] = f"# SDs = {labels[0]}" + legax2.legend(handles=list(handles1.values()), labels=labels, loc=(-2.5, 0.0)) return fig, [ax0, ax0b, ax1, ax2] @@ -333,7 +341,7 @@ def plot_space_time_stack_memory_allocations_vs_nthreads( nsupers, colors=colors, ) -savename = path4plots / "memory_vs_totnsupers.png" +savename = path4plots / "memory_vs_totnsupers.pdf" save_figure(savename) # %% @@ -346,7 +354,7 @@ def plot_space_time_stack_memory_allocations_vs_nthreads( fig, axs = plot_space_time_stack_memory_allocations_vs_nthreads( datasets, {build: ngbxs2plot[build]}, nsupers ) - savename = path4plots / f"memory_vs_totnsupers_{build}.png" + savename = path4plots / f"memory_vs_totnsupers_{build}.pdf" save_figure(savename) # %% From d2e216f54cd47bde682f6803d9db5bd77b452456 Mon Sep 17 00:00:00 2001 From: "clara.bayley" Date: Wed, 14 Jan 2026 14:03:02 +0100 Subject: [PATCH 3/4] refactor: make script compatable with later cleo version using cleopy --- scripts/plotting/prettyplots_thermo3d.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/plotting/prettyplots_thermo3d.py b/scripts/plotting/prettyplots_thermo3d.py index a196496..00e5c91 100644 --- a/scripts/plotting/prettyplots_thermo3d.py +++ b/scripts/plotting/prettyplots_thermo3d.py @@ -34,7 +34,7 @@ ### path to CLEO for pySD module path2CLEO = Path("/home") / "m" / "m300950" / "CLEO" sys.path.append(str(path2CLEO)) -from pySD.sdmout_src import pyzarr, pysetuptxt, pygbxsdat +from cleopy.sdmout_src import pyzarr, pysetuptxt, pygbxsdat ### -------------------------------------- ### @@ -85,7 +85,7 @@ def plot_superdroplet_distribution(fig, ax2, gbxs, sddata): def get_attributes(sddata, attrs, t, gbxindex): vars = [] for attr in attrs: - var = np.where(sddata.sdgbxindex[t] == gbxindex, sddata[attr][t], np.nan) + var = np.where(sddata.sdgbxindex()[t] == gbxindex, sddata[attr][t], np.nan) vars.append(var[~np.isnan(var)]) return vars @@ -217,8 +217,8 @@ def variable_in_ranges(var, subsets): tslice = [ int(np.argmin(abs(t - time.mins))) for t in times2select ] # turn time into time index - set1 = define_variable_subset(sddata.coord1[tslice], coord1_range) - set2 = define_variable_subset(sddata.coord2[tslice], coord2_range) + set1 = define_variable_subset(sddata.coord1()[tslice], coord1_range) + set2 = define_variable_subset(sddata.coord2()[tslice], coord2_range) selected_data = {} for attr in attrs: From 36af14ab17d6f643f5131a8f51083746e4c66e50 Mon Sep 17 00:00:00 2001 From: "clara.bayley" Date: Wed, 14 Jan 2026 14:38:01 +0100 Subject: [PATCH 4/4] refactor: larger fonts and save as pdfs for thermo conditions --- scripts/plotting/prettyplots_thermo3d.py | 49 ++++++++++++++++-------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/scripts/plotting/prettyplots_thermo3d.py b/scripts/plotting/prettyplots_thermo3d.py index 00e5c91..ed98ed2 100644 --- a/scripts/plotting/prettyplots_thermo3d.py +++ b/scripts/plotting/prettyplots_thermo3d.py @@ -50,8 +50,8 @@ ### paths to particular dataset, setup file and grid file buildtype = "cuda" -ngbxs = 2048 -nsupers = 128 +ngbxs = 2048 # 16384 +nsupers = 128 # 256 nthreads = 128 nrun = 0 @@ -69,6 +69,19 @@ setupfile = path2bin / "setup.txt" ### -------------------------------------- ### +# %% font sizes for beautifying plots +SMALL_SIZE = 15 +MEDIUM_SIZE = 16 +BIG_SIZE = 18 + +plt.rc("font", size=SMALL_SIZE) # controls default text sizes +plt.rc("axes", titlesize=BIG_SIZE) # fontsize of the axes title +plt.rc("axes", labelsize=BIG_SIZE) # fontsize of the x and y labels +plt.rc("xtick", labelsize=MEDIUM_SIZE) # fontsize of the tick labels +plt.rc("ytick", labelsize=MEDIUM_SIZE) # fontsize of the tick labels +plt.rc("legend", fontsize=MEDIUM_SIZE) # legend fontsize +plt.rc("figure", titlesize=BIG_SIZE) # fontsize of the figure title + # %% ### --------- plotting functions --------- ### @@ -109,14 +122,16 @@ def get_attributes(sddata, attrs, t, gbxindex): np.log10(radius), bins=hedgs, weights=wghts, density=None ) hcens = (hedgs[1:] + hedgs[:-1]) / 2 - ax2.step(10**hcens, hist, where="mid", color="dimgrey", label="binned distribution") + ax2.step( + 10**hcens, hist, where="mid", color="dimgrey", label="binned\ndistribution" + ) ax2.set_xscale("log") ax2.set_yscale("log") ax2.set_xlim([5e-3, 1]) ax2.set_xlabel("radius /\u03BCm") - ax2.set_ylabel("aerosol number concentration / cm$^{-3}$") - ax2.legend() + ax2.set_ylabel("aerosol number\nconcentration / cm$^{-3}$") + ax2.legend(loc=(0.4, 0.9)) ax2.spines[["right", "top"]].set_visible(False) @@ -136,13 +151,13 @@ def three_xticks(var): ax0.plot(temp, gbxs["zfull"], color="k") ax0.set_xlabel("temperature /K") ax0.set_xticks(three_xticks(temp)) - ax0.set_xticklabels(["{:.2f}".format(x) for x in three_xticks(temp)]) + ax0.set_xticklabels(["{:.1f}".format(x) for x in three_xticks(temp)]) qvap = thermo.qvap[t, y, x, :] # g/Kg ax1.plot(qvap, gbxs["zfull"], color="darkblue") ax1.set_xlabel("q$_{v}$ /g Kg$^{-1}$", color="darkblue") ax1.set_xticks(three_xticks(qvap)) - ax1.set_xticklabels(["{:.2f}".format(x) for x in three_xticks(qvap)]) + ax1.set_xticklabels(["{:.1f}".format(x) for x in three_xticks(qvap)]) ax1b = ax1.twiny() supersat = thermo.supersaturation()[t, y, x, :] * 100 # % @@ -175,7 +190,7 @@ def three_xticks(var): fig.colorbar( ScalarMappable(norm=cmap_norm, cmap=cmap), cax=cax, - label="|wind velocity| /m s${-1}$ ", + label="|wind velocity| /m s$^{-1}$ ", ) ax3.set_xlabel("x /m") @@ -187,11 +202,11 @@ def three_xticks(var): def plot_initial_conditions(gbxs, thermo, sddata): - fig = plt.figure(figsize=(12, 8)) - gs = GridSpec(2, 45, figure=fig, height_ratios=[3, 2]) - ax0 = fig.add_subplot(gs[0, :11]) - ax1 = fig.add_subplot(gs[0, 15:26]) - ax2 = fig.add_subplot(gs[0, 30:]) + fig = plt.figure(figsize=(11.5, 8)) + gs = GridSpec(2, 50, figure=fig, height_ratios=[3, 2], hspace=0.4, wspace=0.01) + ax0 = fig.add_subplot(gs[0, :12]) + ax1 = fig.add_subplot(gs[0, 18:28]) + ax2 = fig.add_subplot(gs[0, 37:]) ax3 = fig.add_subplot(gs[1, :-1]) cax = fig.add_subplot(gs[1, -1]) @@ -308,7 +323,7 @@ def plot_superdroplet_sample_tracing(time, sample, coord1_range): def plot_superdroplet_sample_tracing_version2(sample, coord1_range): - fig = plt.figure(figsize=(7, 6)) + fig = plt.figure(figsize=(7, 5)) gs = GridSpec(1, 2, figure=fig, width_ratios=[21, 1]) ax0 = fig.add_subplot(gs[0, 0]) cax = fig.add_subplot(gs[0, 1]) @@ -362,7 +377,7 @@ def plot_superdroplet_sample_tracing_version2(sample, coord1_range): ### save figure for initial conditions fig, axs = plot_initial_conditions(gbxs, thermo, sddata) savename = path4plots / Path( - f"thermo3d_initial_conditions_ngbxs{ngbxs}_nsupers{nsupers}.png" + f"thermo3d_initial_conditions_ngbxs{ngbxs}_nsupers{nsupers}.pdf" ) save_figure(savename) @@ -384,14 +399,14 @@ def plot_superdroplet_sample_tracing_version2(sample, coord1_range): # %% fig, axs = plot_superdroplet_sample_tracing(time, sample, coord1_range) savename = path4plots / Path( - f"thermo3d_superdroplet_tracing_ngbxs{ngbxs}_nsupers{nsupers}.png" + f"thermo3d_superdroplet_tracing_ngbxs{ngbxs}_nsupers{nsupers}.pdf" ) save_figure(savename) # %% fig, axs = plot_superdroplet_sample_tracing_version2(sample, coord1_range) savename = path4plots / Path( - f"thermo3d_superdroplet_tracing_version2_ngbxs{ngbxs}_nsupers{nsupers}.png" + f"thermo3d_superdroplet_tracing_version2_ngbxs{ngbxs}_nsupers{nsupers}.pdf" ) save_figure(savename) # %%