149def _filter(df, mat_c, type_c, dose_c, temp_c, bin_c, freq_c,
150 material=None, irr_type=None, dose=None, temp=None):
153 m = m[m[mat_c].astype(str).str.contains(material, case=
False)]
155 m = m[m[type_c].astype(str).str.contains(irr_type, case=
False)]
157 m = m[pd.to_numeric(m[dose_c], errors=
"coerce") == dose]
159 m = m[pd.to_numeric(m[temp_c], errors=
"coerce") == temp]
160 return m.dropna(subset=[bin_c, freq_c])
172 xlsx="Ferritics_Irradiated_Microstructure_Data.xlsx",
176 formats=(
"pdf",
"png"),
177 include_overview=
True,
181 font_serif=(
"Times New Roman",
"DejaVu Serif"),
189 Build one figure per condition (loop and void size distributions).
191 Empty datasets are skipped. Returns dict{stem -> Figure} of figures
194 Set `include_overview=False` to skip the mean-loop-size-vs-T scatter.
196 if cite_fontsize
is None:
197 cite_fontsize = max(7, font_size - 4)
199 _apply_style(font_family, font_serif, font_size, axes_linewidth, dpi, save_dpi)
202 os.makedirs(outdir, exist_ok=
True)
207 def col(df, partial):
208 matches = [c
for c
in df.columns
if partial.lower()
in c.lower()]
209 return matches[0]
if matches
else None
211 l_mat, l_type, l_dose, l_temp = (col(loops, k)
for k
in
212 (
"Material",
"Irrad. Type",
"Dose",
"Temp"))
213 l_bin, l_bw, l_freq = (col(loops, k)
for k
in
214 (
"Bin Centre",
"Bin Width",
"Rel. Frequency"))
216 v_mat, v_type, v_dose, v_temp = (col(voids, k)
for k
in
217 (
"Material",
"Irrad. Type",
"Dose",
"Temp"))
218 v_bin, v_bw, v_freq = (col(voids, k)
for k
in
219 (
"Bin Centre",
"Bin Width",
"Rel. Frequency"))
225 for case
in LOOP_CASES:
226 d =
_filter(loops, l_mat, l_type, l_dose, l_temp, l_bin, l_freq,
227 material=case[
"material"], irr_type=case.get(
"irr_type"),
228 dose=case.get(
"dose"), temp=case.get(
"temp"))
229 x, w, y =
_xywh(d, l_bin, l_bw, l_freq)
231 skipped.append((
"loop", case[
"title"]))
234 stem =
"loop_" +
_slug(case[
"title"])
235 fig, ax = plt.subplots(figsize=figsize)
236 ax.bar(x, y, width=w * 0.85, color=case[
"color"],
237 alpha=0.85, edgecolor=
"white", linewidth=0.6)
238 if case.get(
"mean")
is not None:
239 ax.axvline(case[
"mean"], color=case[
"color"], lw=1.8, ls=
"--",
240 alpha=0.9, label=f
"Mean = {case['mean']:.1f} nm")
241 ax.legend(frameon=
False)
242 ax.set_xlabel(
"Loop diameter (nm)")
243 ax.set_ylabel(
"Relative frequency (%)")
244 _set_title(ax, case[
"title"], fontweight=
"bold")
245 ax.set_xlim(*case[
"xlim"])
251 for case
in VOID_CASES:
252 d =
_filter(voids, v_mat, v_type, v_dose, v_temp, v_bin, v_freq,
253 material=case[
"material"], irr_type=case.get(
"irr_type"),
254 dose=case.get(
"dose"), temp=case.get(
"temp"))
255 x, w, y =
_xywh(d, v_bin, v_bw, v_freq)
257 skipped.append((
"void", case[
"title"]))
260 stem =
"void_" +
_slug(case[
"title"])
261 fig, ax = plt.subplots(figsize=figsize)
262 if case.get(
"bimodal"):
265 ax.bar(x[small], y[small], width=w[small] * 0.85,
266 color=
"#2E86C1", alpha=0.85, edgecolor=
"white", lw=0.6,
267 label=
"He-bubbles ($r < r_c$)")
268 ax.bar(x[large], y[large], width=w[large] * 0.85,
269 color=case[
"color"], alpha=0.85, edgecolor=
"white", lw=0.6,
270 label=
"Growing voids ($r > r_c$)")
271 ax.axvline(2.0, color=
"gray", lw=1.2, ls=
":", alpha=0.8,
272 label=
"Approx. critical radius")
273 ax.legend(frameon=
False)
275 ax.bar(x, y, width=w * 0.85, color=case[
"color"],
276 alpha=0.85, edgecolor=
"white", linewidth=0.6)
277 ax.set_xlabel(
"Cavity diameter (nm)")
278 ax.set_ylabel(
"Relative frequency (%)")
279 _set_title(ax, case[
"title"], fontweight=
"bold")
280 ax.set_xlim(*case[
"xlim"])
288 summary_df = pd.read_excel(xlsx, sheet_name=
"Loop Size Distributions", header=3)
289 summary_df.columns = [str(c).strip()
for c
in summary_df.columns]
290 summary_df = summary_df.dropna(how=
"all")
292 mean_col = [c
for c
in summary_df.columns
if "Mean Diam" in c][0]
293 temp_col2 = [c
for c
in summary_df.columns
if "Temp" in c][0]
294 mat_col2 = [c
for c
in summary_df.columns
if "Material" in c][0]
295 type_col2 = [c
for c
in summary_df.columns
if "Irrad. Type" in c][0]
297 fig, ax = plt.subplots(figsize=(figsize[0] + 2, figsize[1] + 0.5))
298 materials = [
"EUROFER97",
"T91",
"HT9",
"Pure Fe",
"Fe-9Cr"]
299 markers = [
"o",
"s",
"^",
"D",
"v"]
300 cols_m = [
"#1B4F8A",
"#117A65",
"#922B21",
"#D4AC0D",
"#6C3483"]
303 for mat, mk, c
in zip(materials, markers, cols_m):
304 sub = summary_df[summary_df[mat_col2].astype(str).str.contains(mat, case=
False)]
305 for _, row
in sub.iterrows():
307 t = float(str(row[temp_col2]).replace(
"~",
""))
308 m_raw = str(row[mean_col]).replace(
"~",
"").replace(
"+",
"").split()[0]
310 is_ion =
"ion" in str(row[type_col2]).lower()
311 fc =
"none" if is_ion
else c
312 ax.scatter(t, m, marker=mk, color=c, facecolors=fc,
313 s=80, zorder=5, linewidths=1.5)
319 legend_patches = [plt.scatter([], [], marker=mk, color=c, s=70, label=mat)
320 for mat, mk, c
in zip(materials, markers, cols_m)]
322 mpatches.Patch(facecolor=
"gray", edgecolor=
"gray", alpha=0.8,
323 label=
"Filled = neutron"),
324 mpatches.Patch(facecolor=
"none", edgecolor=
"gray", linewidth=1.5,
327 ax.legend(handles=legend_patches, frameon=
False, ncol=2, loc=
"upper left")
328 ax.set_xlabel(
"Irradiation temperature (°C)")
329 ax.set_ylabel(
"Mean loop diameter (nm)")
330 _set_title(ax,
"Mean Dislocation Loop Diameter vs Irradiation Temperature",
332 ax.set_xlim(50, 650); ax.set_ylim(0, 35)
333 ax.grid(
True, ls=
":", alpha=0.4)
335 out[
"overview_mean_loop_size_vs_temperature"] = fig
338 skipped.append((
"overview",
"mean loop size vs T (no parseable rows)"))
339 except Exception
as e:
340 skipped.append((
"overview", f
"failed: {e}"))
343 for stem, fig
in out.items():
344 _save(fig, outdir, stem, formats=formats)
345 print(f
"Saved {len(out)} figure(s) to {os.path.abspath(outdir)}/")
348 print(f
"Skipped {len(skipped)} figure(s) (no data):")
349 for kind, title
in skipped:
350 print(f
" [{kind}] {title}")
353 for fig
in out.values():
plot_size_distributions(xlsx="Ferritics_Irradiated_Microstructure_Data.xlsx", outdir="figures", save=True, show=False, formats=("pdf", "png"), include_overview=True, font_size=16, font_family="serif", font_serif=("Times New Roman", "DejaVu Serif"), axes_linewidth=1.2, dpi=150, save_dpi=300, cite_fontsize=None, figsize=(8, 5))