.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/particle/detector_signatures/plot_02_cascade_showers.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_particle_detector_signatures_plot_02_cascade_showers.py: Bhabha and Heitler's cascade theory of cosmic-ray showers ================================================================ Bhabha, Heitler, Carlson, and Oppenheimer (1937) explained the cosmic-ray "transition curve" -- the number of shower particles first growing, then shrinking, with depth -- as a branching cascade: a single high-energy electron, positron, or photon alternately radiates a photon or materializes one into an electron-positron pair, each product repeating the process until individual energies fall low enough for ordinary ionization losses to take over. This example builds exactly this kind of branching cascade with :func:`~physicskit.particle.collider.simple_shower`, checks that its total four-momentum is conserved from the single primary particle down to every final-state leaf, and shows the exponential growth in particle count with generation that gives the transition curve its characteristic rise. .. GENERATED FROM PYTHON SOURCE LINES 21-28 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from physicskit.particle.collider import flatten_shower, simple_shower from physicskit.particle.kinematics import invariant_mass from physicskit.particle.visualizers import animate_particle_cascade .. GENERATED FROM PYTHON SOURCE LINES 29-31 A branching cascade from one 100 GeV primary --------------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 31-41 .. code-block:: Python rng = np.random.default_rng(3) root = simple_shower(100.0, E_threshold=2.0, rng=rng) nodes = flatten_shower(root) leaves = [n for n in nodes if n.is_leaf] print(f"primary particle energy: {root.four_vector.E:.3f} GeV") print(f"total nodes in the cascade tree: {len(nodes)}") print(f"final-state (leaf) particles: {len(leaves)}") print(f"max generation reached: {max(n.generation for n in nodes)}") .. rst-class:: sphx-glr-script-out .. code-block:: none primary particle energy: 100.000 GeV total nodes in the cascade tree: 143 final-state (leaf) particles: 72 max generation reached: 8 .. GENERATED FROM PYTHON SOURCE LINES 42-48 Four-momentum conservation, from primary down to every leaf ------------------------------------------------------------------ Every branching is an exact two-body decay reusing already-tested kinematics building blocks, so the invariant mass of the *entire* final state should reproduce the primary particle's own mass exactly, no matter how many generations deep the cascade went. .. GENERATED FROM PYTHON SOURCE LINES 48-53 .. code-block:: Python reconstructed_mass = invariant_mass([leaf.four_vector for leaf in leaves]) print(f"\nprimary particle's own (virtuality) mass: {root.four_vector.mass:.8f} GeV") print(f"invariant mass reconstructed from ALL {len(leaves)} final-state leaves: {reconstructed_mass:.8f} GeV") print(f"difference: {abs(reconstructed_mass - root.four_vector.mass):.2e} GeV (machine precision)") .. rst-class:: sphx-glr-script-out .. code-block:: none primary particle's own (virtuality) mass: 30.00000000 GeV invariant mass reconstructed from ALL 72 final-state leaves: 30.00000000 GeV difference: 1.21e-13 GeV (machine precision) .. GENERATED FROM PYTHON SOURCE LINES 54-60 Particle count growing, then the cascade dying out -------------------------------------------------------- Counting nodes by generation shows the multiplication Bhabha, Heitler, Carlson, and Oppenheimer derived: roughly doubling generation over generation while energy remains available, then stopping abruptly once every branch has fallen below the energy threshold. .. GENERATED FROM PYTHON SOURCE LINES 60-69 .. code-block:: Python max_gen = max(n.generation for n in nodes) counts_by_generation = [sum(1 for n in nodes if n.generation == g) for g in range(max_gen + 1)] print("\nparticles per generation (roughly doubling, then the cascade terminates):") for g, c in enumerate(counts_by_generation): print(f" generation {g}: {c} particles") anim = animate_particle_cascade(root) plt.show() .. container:: sphx-glr-animation .. raw:: html .. rst-class:: sphx-glr-script-out .. code-block:: none particles per generation (roughly doubling, then the cascade terminates): generation 0: 1 particles generation 1: 2 particles generation 2: 4 particles generation 3: 8 particles generation 4: 16 particles generation 5: 30 particles generation 6: 34 particles generation 7: 36 particles generation 8: 12 particles .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 4.836 seconds) .. _sphx_glr_download_api_gallery_particle_detector_signatures_plot_02_cascade_showers.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_02_cascade_showers.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_02_cascade_showers.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_02_cascade_showers.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_