今回は前回のコードに、細かい設定を加えていきます。

具体的には、物理リストとカットオフを明示、統計情報の詳細にアクセスしていきます。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Thme01: 
- 80 keV ガンマ線を水ファントムに照射
- 統計情報を取得
"""

import opengate as gate
from opengate.utility import g4_units

# ============================================================================
# シミュレーション設定
# ============================================================================

# Simulationオブジェクトの作成
sim = gate.Simulation()

# 単位の定義
m = g4_units.m
cm = g4_units.cm
mm = g4_units.mm
keV = g4_units.keV
MeV = g4_units.MeV
Bq = g4_units.Bq
sec = g4_units.second


# ============================================================================
# User-tunable settings for exercises
# ============================================================================

CONFIG = {
    "source_particle": "gamma",
    "source_energy_keV": 511.0,
    "source_n": 200000,
    "phantom_material": "G4_WATER",
    "phantom_size_cm": [40.0, 40.0, 40.0],
    "phantom_translation_cm": [0.0, 0.0, 25.0],
}

# ============================================================================
# World(最上位ボリューム)の設定
# ============================================================================

world = sim.world
world.size = [ 3 * m, 3 * m, 3 * m ]
world.material = "G4_AIR"

# ============================================================================
# 水ファントムの作成
# ============================================================================

waterbox = sim.add_volume("Box", "Waterbox")
waterbox.size = [x * cm for x in CONFIG["phantom_size_cm"]]
waterbox.translation = [x * cm for x in CONFIG["phantom_translation_cm"]]
waterbox.material = CONFIG["phantom_material"]
waterbox.color = [0, 0, 1, 0.3]  # 青色、半透明

# ============================================================================
# ガンマ線源の設定
# ============================================================================

source = sim.add_source("GenericSource", "gamma_source")
source.particle = CONFIG["source_particle"]
source.energy.mono = CONFIG["source_energy_keV"] * keV
source.position.type = "point"  # 点線源
source.position.translation = [0, 0, -10 * cm]  # 線源位置: ファントム前方10 cm
source.direction.type = "momentum"  # 運動量方向指定
source.direction.momentum = [0, 0, 1]  # Z軸正方向
source.n = CONFIG["source_n"]

# ============================================================================
# 物理プロセスの設定
# ============================================================================

# デフォルトの物理リストを使用
sim.physics_manager.physics_list_name = "QGSP_BERT_EMV"

# エネルギーカットオフ(オプション)
sim.physics_manager.global_production_cuts.gamma = 0.1 * mm
sim.physics_manager.global_production_cuts.electron = 0.1 * mm
sim.physics_manager.global_production_cuts.positron = 0.1 * mm
sim.physics_manager.global_production_cuts.proton = 0.1 * mm

# ============================================================================
# 統計情報アクターの追加
# ============================================================================

stats = sim.add_actor("SimulationStatisticsActor", "Stats")
stats.track_types_flag = True  # 粒子種別ごとのトラック数を記録

# ============================================================================
# シミュレーションの実行
# ============================================================================

print("=" * 80)
print("テーマ1: 基礎 - 最初のモンテカルロシミュレーション")
print("=" * 80)
print(f"粒子種類: {source.particle}")
print(f"エネルギー: {source.energy.mono / keV:.1f} keV")
print(f"粒子数: {source.n:,}")
print(f"ファントム材質: {waterbox.material}")
print(
    f"ファントムサイズ: {waterbox.size[0] / cm:.1f} x {waterbox.size / cm:.1f} x {waterbox.size / cm:.1f} cm"
)
print("=" * 80)
print("\nシミュレーション開始...")

# シミュレーション実行
sim.run()

print("\nシミュレーション完了!")
print("=" * 80)

# ============================================================================
# 結果の表示
# ============================================================================

print("\n【統計情報】")
print(stats)

# 詳細な統計情報を取得
output = sim.get_actor("Stats")

# 統計情報(counts)で利用可能な項目を一覧表示するには、下記のコメントアウトを解除してください
# print(output.counts.keys())

print("\n【詳細統計】")
duration_s = output.counts.duration * 1e-9  # ns -> s
print(f"総実行時間: {duration_s:.2f} 秒")
print(f"総トラック数: {output.counts.tracks:,}")
print(f"総ステップ数: {output.counts.steps:,}")
print(f"総イベント数: {output.counts.events:,}")
print(f"1秒あたりの粒子数 (PPS): {(output.counts.events / duration_s):.2e}")

# 粒子種別ごとの統計
if output.counts.track_types:
    print("\n【粒子種別トラック数】")
    for particle, count in sorted(output.counts.track_types.items()):
        print(f"  {particle:15s}: {count:,}")

print("\n" + "=" * 80)
print("このシミュレーションでは以下のことを学びました:")
print("1. GATE10の基本構造(World, Volume, Source, Actor)")
print("2. ガンマ線と物質の相互作用")
print("3. 二次粒子の生成(電子、陽電子)")
print("4. シミュレーションの統計情報の読み方")
print("=" * 80)

このほかにも色々と変えて、理解を深めてください。