254 lines
6.4 KiB
Python
254 lines
6.4 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
import pandas as pd
|
||
|
|
import numpy as np
|
||
|
|
import matplotlib.pyplot as plt
|
||
|
|
from pathlib import Path
|
||
|
|
import sys
|
||
|
|
from matplotlib.lines import Line2D
|
||
|
|
|
||
|
|
sys.path.append(str(Path(__file__).resolve().parents[1]))
|
||
|
|
import plotstyle
|
||
|
|
|
||
|
|
MODE = "paper"
|
||
|
|
plotstyle.set_style(MODE)
|
||
|
|
|
||
|
|
WITH_ELECTRON = False
|
||
|
|
PLOT_ELECTRON_ONLY = False
|
||
|
|
|
||
|
|
PARTICLES_BASE_NEW = {
|
||
|
|
'proton': 'outBGO/threeBGO_prob_proton.0.hits',
|
||
|
|
'alpha': 'outBGO/threeBGO_prob_helium.0.hits',
|
||
|
|
'mu-': 'outBGO/threeBGO_prob_muon.0.hits',
|
||
|
|
'e-': 'outBGO/threeBGO_electron1000.0.hits'
|
||
|
|
}
|
||
|
|
|
||
|
|
colors = {
|
||
|
|
'proton': 'red',
|
||
|
|
'alpha': 'green',
|
||
|
|
'mu-': (0.5, 0.3, 0.8),
|
||
|
|
'e-': 'blue'
|
||
|
|
}
|
||
|
|
|
||
|
|
LABELS = {
|
||
|
|
'proton': 'Proton',
|
||
|
|
'alpha': 'Helium',
|
||
|
|
'mu-': 'Muon',
|
||
|
|
'e-': 'Electron'
|
||
|
|
}
|
||
|
|
|
||
|
|
LINSTYLES = {
|
||
|
|
2: '-',
|
||
|
|
4: '--',
|
||
|
|
6: ':'
|
||
|
|
}
|
||
|
|
|
||
|
|
THICKNESSES = [2, 4, 6]
|
||
|
|
DETECTOR_MAP = {
|
||
|
|
2: ['B1'],
|
||
|
|
4: ['B1', 'B2'],
|
||
|
|
6: ['B1', 'B2', 'B3']
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def load_stopprob_data(filename, part_name, label):
|
||
|
|
try:
|
||
|
|
columns = ['event', 'track', 'det', 'primaryE', 'edep', 'nioni']
|
||
|
|
df = pd.read_csv(filename, sep=r'\s+', comment='#', names=columns)
|
||
|
|
df = df[df['track'] == 1].copy()
|
||
|
|
|
||
|
|
if len(df) == 0:
|
||
|
|
print(f" -> {label}: KEINE Primärteilchen gefunden!")
|
||
|
|
return None
|
||
|
|
|
||
|
|
all_stats = []
|
||
|
|
|
||
|
|
for thickness, detectors in DETECTOR_MAP.items():
|
||
|
|
df_sel = df[df['det'].isin(detectors)].copy()
|
||
|
|
|
||
|
|
if len(df_sel) == 0:
|
||
|
|
continue
|
||
|
|
|
||
|
|
df_sel['edep_abs'] = df_sel['edep'].abs()
|
||
|
|
|
||
|
|
df_event = (
|
||
|
|
df_sel
|
||
|
|
.groupby(['event', 'primaryE'])['edep_abs']
|
||
|
|
.sum()
|
||
|
|
.reset_index()
|
||
|
|
)
|
||
|
|
|
||
|
|
df_event['stopped'] = (df_event['edep_abs'] >= 0.999 * df_event['primaryE']).astype(int)
|
||
|
|
|
||
|
|
hit_stats = (
|
||
|
|
df_event
|
||
|
|
.groupby('primaryE')['stopped']
|
||
|
|
.agg(['mean', 'count'])
|
||
|
|
.reset_index()
|
||
|
|
)
|
||
|
|
|
||
|
|
hit_stats.columns = ['E0', 'stop_prob', 'N']
|
||
|
|
hit_stats['stop_prob'] *= 100.0
|
||
|
|
hit_stats['thickness'] = thickness
|
||
|
|
all_stats.append(hit_stats)
|
||
|
|
|
||
|
|
if len(all_stats) == 0:
|
||
|
|
return None
|
||
|
|
|
||
|
|
return pd.concat(all_stats, ignore_index=True)
|
||
|
|
|
||
|
|
except FileNotFoundError:
|
||
|
|
print(f" -> Datei '{filename}' nicht gefunden!")
|
||
|
|
return None
|
||
|
|
except Exception as e:
|
||
|
|
print(f" -> Fehler bei {label}: {e}")
|
||
|
|
return None
|
||
|
|
|
||
|
|
|
||
|
|
all_stats = {}
|
||
|
|
|
||
|
|
for part_g4 in PARTICLES_BASE_NEW.keys():
|
||
|
|
if part_g4 == 'e-' and not WITH_ELECTRON:
|
||
|
|
continue
|
||
|
|
|
||
|
|
if PLOT_ELECTRON_ONLY and part_g4 != 'e-':
|
||
|
|
continue
|
||
|
|
|
||
|
|
label = LABELS[part_g4]
|
||
|
|
filename = PARTICLES_BASE_NEW[part_g4]
|
||
|
|
|
||
|
|
print(f"\n=== {label} stopping probability ({part_g4}) ===")
|
||
|
|
print(f" Datei: {filename}")
|
||
|
|
|
||
|
|
df = load_stopprob_data(filename, part_g4, label)
|
||
|
|
|
||
|
|
if df is None:
|
||
|
|
print(f" -> {label}: KEINE DATEN")
|
||
|
|
continue
|
||
|
|
|
||
|
|
print(f" -> {label}: {len(df)} Energien")
|
||
|
|
|
||
|
|
for thickness in THICKNESSES:
|
||
|
|
df_thick = df[df['thickness'] == thickness].copy()
|
||
|
|
if len(df_thick) > 0:
|
||
|
|
all_stats[(part_g4, thickness)] = df_thick
|
||
|
|
else:
|
||
|
|
print(f" -> {label} / {thickness} cm: KEINE DATEN")
|
||
|
|
all_stats[(part_g4, thickness)] = None
|
||
|
|
|
||
|
|
|
||
|
|
print("\n=== Stopping probability [%] pro Startenergie ===")
|
||
|
|
for (part_g4, thickness), df in all_stats.items():
|
||
|
|
label = LABELS[part_g4]
|
||
|
|
thickness_label = f"{thickness} cm"
|
||
|
|
if df is not None:
|
||
|
|
print(f"\n{label} ({thickness_label}):")
|
||
|
|
print(df.round(3))
|
||
|
|
else:
|
||
|
|
print(f"\n{label} ({thickness_label}): KEINE DATEN")
|
||
|
|
|
||
|
|
|
||
|
|
plt.figure()
|
||
|
|
plotted_particles = set()
|
||
|
|
|
||
|
|
for (part_g4, thickness), stats in all_stats.items():
|
||
|
|
if stats is None or len(stats) == 0:
|
||
|
|
continue
|
||
|
|
|
||
|
|
color = colors.get(part_g4, 'black')
|
||
|
|
linestyle = LINSTYLES[thickness]
|
||
|
|
|
||
|
|
x = stats['E0']
|
||
|
|
y = stats['stop_prob']
|
||
|
|
n = stats['N']
|
||
|
|
yerr = np.sqrt((y / 100.0) * (1.0 - y / 100.0) / n) * 100.0 *3
|
||
|
|
|
||
|
|
# Energie bestimmen, bei der die 50%-Schwelle unterschritten wird
|
||
|
|
if np.any(y <= 50):
|
||
|
|
|
||
|
|
idx = np.where(y <= 50)[0][0]
|
||
|
|
|
||
|
|
if idx > 0:
|
||
|
|
# lineare Interpolation zwischen den beiden Punkten um E50 genauer zu bestimmen
|
||
|
|
x1, x2 = x.iloc[idx - 1], x.iloc[idx]
|
||
|
|
y1, y2 = y.iloc[idx - 1], y.iloc[idx]
|
||
|
|
|
||
|
|
E50 = x1 + (50.0 - y1) * (x2 - x1) / (y2 - y1)
|
||
|
|
else:
|
||
|
|
E50 = x.iloc[0]
|
||
|
|
|
||
|
|
plt.axvline(
|
||
|
|
E50,
|
||
|
|
color=color,
|
||
|
|
linestyle=linestyle,
|
||
|
|
linewidth=1,
|
||
|
|
alpha=0.7
|
||
|
|
)
|
||
|
|
|
||
|
|
plt.text(
|
||
|
|
E50 * 0.9,
|
||
|
|
45, # y-ausrichtung
|
||
|
|
f"{E50:.0f} MeV",
|
||
|
|
rotation=90,
|
||
|
|
color=color,
|
||
|
|
fontsize=22,
|
||
|
|
ha='left',
|
||
|
|
va='center'
|
||
|
|
)
|
||
|
|
|
||
|
|
# plt.errorbar(
|
||
|
|
# x, y, yerr=yerr,
|
||
|
|
# color=color,
|
||
|
|
# linestyle=linestyle,
|
||
|
|
# marker='None',
|
||
|
|
# linewidth=2,
|
||
|
|
# capsize=2,
|
||
|
|
# label=f"{LABELS[part_g4]} ({thickness} cm)"
|
||
|
|
# )
|
||
|
|
|
||
|
|
plt.plot(
|
||
|
|
x, y,
|
||
|
|
color=color,
|
||
|
|
linestyle=linestyle,
|
||
|
|
linewidth=2,
|
||
|
|
label=f"{LABELS[part_g4]} ({thickness} cm)"
|
||
|
|
)
|
||
|
|
|
||
|
|
plt.fill_between(
|
||
|
|
x,
|
||
|
|
y - yerr,
|
||
|
|
y + yerr,
|
||
|
|
color=color,
|
||
|
|
alpha=0.2
|
||
|
|
)
|
||
|
|
|
||
|
|
plotted_particles.add(part_g4)
|
||
|
|
|
||
|
|
plt.xscale('log')
|
||
|
|
plt.ylim(-2, 102)
|
||
|
|
plt.xlim(29, 3000)
|
||
|
|
plt.xlabel('Start energy $E_0$ in MeV')
|
||
|
|
#plt.ylabel("Stopping probability in %")
|
||
|
|
plt.ylabel(r"$\mathrm{Stopping\ probability\ in\ \%}$")
|
||
|
|
plt.grid(True, which='both', ls='--', lw=0.5)
|
||
|
|
|
||
|
|
legend_particle_handles = []
|
||
|
|
for part in ['proton', 'alpha', 'mu-', 'e-']:
|
||
|
|
if part not in plotted_particles:
|
||
|
|
continue
|
||
|
|
legend_particle_handles.append(
|
||
|
|
Line2D([0], [0], color=colors[part], lw=2, label=LABELS[part])
|
||
|
|
)
|
||
|
|
|
||
|
|
legend_thickness_handles = [
|
||
|
|
Line2D([0], [0], color='black', linestyle='-', lw=2, label='2 cm'),
|
||
|
|
Line2D([0], [0], color='black', linestyle='--', lw=2, label='4 cm'),
|
||
|
|
Line2D([0], [0], color='black', linestyle=':', lw=2, label='6 cm')
|
||
|
|
]
|
||
|
|
|
||
|
|
legend1 = plt.legend(handles=legend_particle_handles, loc='upper right', title='Particles')
|
||
|
|
legend2 = plt.legend(handles=legend_thickness_handles, loc='lower right', title='BGO thickness')
|
||
|
|
plt.gca().add_artist(legend1)
|
||
|
|
|
||
|
|
plt.tight_layout()
|
||
|
|
plotstyle.savefig("BGO_stopping_probability_246cm", category="BB")
|
||
|
|
plt.show()
|