handoverlab 2.4.0__tar.gz → 2.4.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. handoverlab-2.4.2/.zenodo.json +39 -0
  2. {handoverlab-2.4.0 → handoverlab-2.4.2}/CHANGELOG.md +59 -1
  3. {handoverlab-2.4.0 → handoverlab-2.4.2}/CITATION.cff +16 -7
  4. {handoverlab-2.4.0 → handoverlab-2.4.2}/PKG-INFO +122 -18
  5. {handoverlab-2.4.0 → handoverlab-2.4.2}/README.md +121 -17
  6. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/calibration-3gpp.md +3 -2
  7. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/comparison.md +2 -2
  8. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/beams-layers.md +9 -8
  9. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/buffers.md +15 -9
  10. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/daps-ltm.md +4 -0
  11. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/dual-connectivity.md +4 -0
  12. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/fading.md +11 -3
  13. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/indoor-rural.md +17 -15
  14. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/learning-rule.md +4 -3
  15. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/mro.md +15 -9
  16. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/scheduler.md +12 -6
  17. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/ue-beams.md +4 -0
  18. handoverlab-2.4.2/docs/images/ai-mobility.png +0 -0
  19. handoverlab-2.4.2/docs/images/buffers.png +0 -0
  20. handoverlab-2.4.2/docs/images/calibration_7ghz.png +0 -0
  21. handoverlab-2.4.2/docs/images/dashboard-charts.png +0 -0
  22. handoverlab-2.4.2/docs/images/dashboard-compare.png +0 -0
  23. handoverlab-2.4.2/docs/images/dashboard-where.png +0 -0
  24. handoverlab-2.4.2/docs/images/dashboard.png +0 -0
  25. handoverlab-2.4.2/docs/images/dual-connectivity.png +0 -0
  26. handoverlab-2.4.2/docs/images/fading.png +0 -0
  27. handoverlab-2.4.2/docs/images/mro.png +0 -0
  28. handoverlab-2.4.2/docs/images/new-scenarios.png +0 -0
  29. handoverlab-2.4.2/docs/images/procedures.png +0 -0
  30. handoverlab-2.4.2/docs/images/report-comparison.png +0 -0
  31. handoverlab-2.4.2/docs/images/report-tuning.png +0 -0
  32. handoverlab-2.4.2/docs/images/scheduler.png +0 -0
  33. handoverlab-2.4.2/docs/images/traffic.png +0 -0
  34. handoverlab-2.4.2/docs/images/ue-beams.png +0 -0
  35. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/index.md +8 -4
  36. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/performance.md +19 -5
  37. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/indoor-office-4ghz.md +1 -1
  38. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/rural-700mhz.md +1 -1
  39. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/suburban-sma-7ghz.md +1 -1
  40. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/stability.md +1 -0
  41. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/standard-compliance.md +1 -1
  42. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/tutorials/first-run.md +13 -8
  43. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/tutorials/own-rule.md +10 -9
  44. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/tutorials/reading-the-report.md +25 -23
  45. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/tutorials/tuning-study.md +43 -25
  46. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/user_guide.md +27 -14
  47. {handoverlab-2.4.0 → handoverlab-2.4.2}/examples/study_smoke.yaml +1 -1
  48. {handoverlab-2.4.0 → handoverlab-2.4.2}/pyproject.toml +1 -1
  49. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/__init__.py +1 -1
  50. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/indoor-office-4ghz.yaml +1 -1
  51. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/rural-700mhz.yaml +1 -1
  52. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/suburban-sma-7ghz.yaml +1 -1
  53. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab.egg-info/PKG-INFO +122 -18
  54. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab.egg-info/SOURCES.txt +23 -0
  55. handoverlab-2.4.2/tools/make_ai_mobility_figure.py +111 -0
  56. handoverlab-2.4.2/tools/make_buffers_figure.py +107 -0
  57. handoverlab-2.4.2/tools/make_calibration_7ghz_figure.py +90 -0
  58. handoverlab-2.4.2/tools/make_dashboard_screenshots.py +219 -0
  59. handoverlab-2.4.2/tools/make_dc_figure.py +127 -0
  60. handoverlab-2.4.2/tools/make_fading_figure.py +127 -0
  61. handoverlab-2.4.2/tools/make_mro_figure.py +135 -0
  62. handoverlab-2.4.2/tools/make_procedures_figure.py +107 -0
  63. handoverlab-2.4.2/tools/make_scenarios_figure.py +136 -0
  64. handoverlab-2.4.2/tools/make_scheduler_figure.py +138 -0
  65. handoverlab-2.4.2/tools/make_traffic_figure.py +84 -0
  66. handoverlab-2.4.2/tools/make_ue_beams_figure.py +123 -0
  67. handoverlab-2.4.0/.zenodo.json +0 -34
  68. handoverlab-2.4.0/docs/images/dashboard-charts.png +0 -0
  69. handoverlab-2.4.0/docs/images/dashboard-compare.png +0 -0
  70. handoverlab-2.4.0/docs/images/dashboard-where.png +0 -0
  71. handoverlab-2.4.0/docs/images/dashboard.png +0 -0
  72. handoverlab-2.4.0/docs/images/report-comparison.png +0 -0
  73. handoverlab-2.4.0/docs/images/report-tuning.png +0 -0
  74. {handoverlab-2.4.0 → handoverlab-2.4.2}/CODE_OF_CONDUCT.md +0 -0
  75. {handoverlab-2.4.0 → handoverlab-2.4.2}/CONTRIBUTING.md +0 -0
  76. {handoverlab-2.4.0 → handoverlab-2.4.2}/LICENSE +0 -0
  77. {handoverlab-2.4.0 → handoverlab-2.4.2}/MANIFEST.in +0 -0
  78. {handoverlab-2.4.0 → handoverlab-2.4.2}/SECURITY.md +0 -0
  79. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/RELEASING.md +0 -0
  80. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/calibration.md +0 -0
  81. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/add-scenario.md +0 -0
  82. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/ai-mobility.md +0 -0
  83. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/dashboard.md +0 -0
  84. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/export-event-logs.md +0 -0
  85. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/high-speed-train.md +0 -0
  86. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/highway.md +0 -0
  87. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/many-cores.md +0 -0
  88. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/ntn.md +0 -0
  89. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/radio-maps.md +0 -0
  90. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/reproduce.md +0 -0
  91. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/suburban-o2i.md +0 -0
  92. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/guides/upper-mid-band.md +0 -0
  93. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/images/calibration_38901.png +0 -0
  94. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/images/ntn-beams.png +0 -0
  95. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/images/radio-map.png +0 -0
  96. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/images/ssb-beams.png +0 -0
  97. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/migration-2.0.md +0 -0
  98. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/config.md +0 -0
  99. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/engine.md +0 -0
  100. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/eventlog.md +0 -0
  101. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/gui.md +0 -0
  102. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/index.md +0 -0
  103. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/mapfile.md +0 -0
  104. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/ntn.md +0 -0
  105. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/rules.md +0 -0
  106. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/scenarios.md +0 -0
  107. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/simulate.md +0 -0
  108. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/stability.md +0 -0
  109. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/stats.md +0 -0
  110. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/studies.md +0 -0
  111. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/testing.md +0 -0
  112. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/api/verify.md +0 -0
  113. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/cli.md +0 -0
  114. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference/metrics.md +0 -0
  115. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/reference-study.md +0 -0
  116. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/dense-urban-2layer.md +0 -0
  117. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/dense-urban-2layer.svg +0 -0
  118. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/fr3-urban-15ghz.md +0 -0
  119. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/fr3-urban-15ghz.svg +0 -0
  120. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/highway-tr37885-30ghz.md +0 -0
  121. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/highway-tr37885-30ghz.svg +0 -0
  122. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/highway-tr37885-4ghz.md +0 -0
  123. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/highway-tr37885-4ghz.svg +0 -0
  124. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/hst-fr2-28ghz.md +0 -0
  125. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/hst-fr2-28ghz.svg +0 -0
  126. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/indoor-office-4ghz.svg +0 -0
  127. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/ns3-urban-3.5ghz.md +0 -0
  128. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/ns3-urban-3.5ghz.svg +0 -0
  129. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/ntn-leo600-2ghz.md +0 -0
  130. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/ntn-leo600-2ghz.svg +0 -0
  131. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/open-area-10ghz.md +0 -0
  132. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/open-area-10ghz.svg +0 -0
  133. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/rural-700mhz.svg +0 -0
  134. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/smoke.md +0 -0
  135. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/smoke.svg +0 -0
  136. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/suburban-sma-7ghz.svg +0 -0
  137. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/urban-grid-10ghz.md +0 -0
  138. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/urban-grid-10ghz.svg +0 -0
  139. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/urban-grid-28ghz-beams.md +0 -0
  140. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/urban-grid-28ghz-beams.svg +0 -0
  141. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/urban-macro-tr37885-4ghz.md +0 -0
  142. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/scenarios/urban-macro-tr37885-4ghz.svg +0 -0
  143. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/time-step.md +0 -0
  144. {handoverlab-2.4.0 → handoverlab-2.4.2}/docs/verification.md +0 -0
  145. {handoverlab-2.4.0 → handoverlab-2.4.2}/examples/compare_a3_cho.py +0 -0
  146. {handoverlab-2.4.0 → handoverlab-2.4.2}/examples/open_area.toml +0 -0
  147. {handoverlab-2.4.0 → handoverlab-2.4.2}/examples/radio_map.py +0 -0
  148. {handoverlab-2.4.0 → handoverlab-2.4.2}/examples/smoke.yaml +0 -0
  149. {handoverlab-2.4.0 → handoverlab-2.4.2}/examples/speed_rule.py +0 -0
  150. {handoverlab-2.4.0 → handoverlab-2.4.2}/examples/street_grid.yaml +0 -0
  151. {handoverlab-2.4.0 → handoverlab-2.4.2}/examples/study_reference.yaml +0 -0
  152. {handoverlab-2.4.0 → handoverlab-2.4.2}/examples/study_reference_explore.yaml +0 -0
  153. {handoverlab-2.4.0 → handoverlab-2.4.2}/examples/traffic_models.py +0 -0
  154. {handoverlab-2.4.0 → handoverlab-2.4.2}/mkdocs.yml +0 -0
  155. {handoverlab-2.4.0 → handoverlab-2.4.2}/setup.cfg +0 -0
  156. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/__main__.py +0 -0
  157. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/channel/__init__.py +0 -0
  158. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/channel/antenna.py +0 -0
  159. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/channel/extended.py +0 -0
  160. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/channel/fading.py +0 -0
  161. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/channel/l2s.py +0 -0
  162. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/channel/ntn.py +0 -0
  163. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/channel/pathloss.py +0 -0
  164. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/channel/radiomap.py +0 -0
  165. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/channel/source.py +0 -0
  166. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/cli.py +0 -0
  167. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/config.py +0 -0
  168. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/engine/__init__.py +0 -0
  169. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/engine/_kernels.py +0 -0
  170. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/engine/batch.py +0 -0
  171. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/engine/buffers.py +0 -0
  172. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/engine/core.py +0 -0
  173. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/engine/dual.py +0 -0
  174. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/engine/extended.py +0 -0
  175. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/engine/invariants.py +0 -0
  176. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/engine/metrics.py +0 -0
  177. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/engine/procedures.py +0 -0
  178. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/engine/scheduler.py +0 -0
  179. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/eventlog.py +0 -0
  180. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/gui/__init__.py +0 -0
  181. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/gui/app.py +0 -0
  182. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/gui/logic.py +0 -0
  183. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/io.py +0 -0
  184. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/layout.py +0 -0
  185. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/linklevel.py +0 -0
  186. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/mapfile.py +0 -0
  187. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/measurement.py +0 -0
  188. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/mobility.py +0 -0
  189. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/py.typed +0 -0
  190. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/requirements.py +0 -0
  191. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/rules/__init__.py +0 -0
  192. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/rules/base.py +0 -0
  193. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/rules/builtin.py +0 -0
  194. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/rules/dqn.py +0 -0
  195. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/rules/mro.py +0 -0
  196. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/rules/predict.py +0 -0
  197. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/__init__.py +0 -0
  198. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/dense-urban-2layer.yaml +0 -0
  199. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/fr3-urban-15ghz.yaml +0 -0
  200. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/highway-tr37885-30ghz.yaml +0 -0
  201. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/highway-tr37885-4ghz.yaml +0 -0
  202. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/hst-fr2-28ghz.yaml +0 -0
  203. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/ns3-urban-3.5ghz.yaml +0 -0
  204. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/ntn-leo600-2ghz.yaml +0 -0
  205. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/open-area-10ghz.yaml +0 -0
  206. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/smoke.yaml +0 -0
  207. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/urban-grid-10ghz.yaml +0 -0
  208. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/urban-grid-28ghz-beams.yaml +0 -0
  209. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/scenarios/cards/urban-macro-tr37885-4ghz.yaml +0 -0
  210. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/seeds.py +0 -0
  211. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/simulate.py +0 -0
  212. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/stability.py +0 -0
  213. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/standard.py +0 -0
  214. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/stats.py +0 -0
  215. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/studies/__init__.py +0 -0
  216. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/studies/config.py +0 -0
  217. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/studies/report.py +0 -0
  218. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/studies/runner.py +0 -0
  219. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/studies/status.py +0 -0
  220. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/studies/store.py +0 -0
  221. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/studies/study.py +0 -0
  222. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/studies/tuning.py +0 -0
  223. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/testing.py +0 -0
  224. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/traffic.py +0 -0
  225. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/__init__.py +0 -0
  226. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/aimobility.py +0 -0
  227. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/calibration.py +0 -0
  228. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/data/golden.json +0 -0
  229. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/data/golden_1x.json +0 -0
  230. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/data/ns3_urban_a3.json +0 -0
  231. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/data/r1_165974.csv +0 -0
  232. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/data/r1_2506406.csv +0 -0
  233. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/engine_checks.py +0 -0
  234. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/extended.py +0 -0
  235. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/fading.py +0 -0
  236. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/golden.py +0 -0
  237. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/highway.py +0 -0
  238. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/learning.py +0 -0
  239. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/ns3.py +0 -0
  240. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/ntn.py +0 -0
  241. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/radio.py +0 -0
  242. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/report.py +0 -0
  243. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/scenarios.py +0 -0
  244. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/stored.py +0 -0
  245. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/verify/values.py +0 -0
  246. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab/world.py +0 -0
  247. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab.egg-info/dependency_links.txt +0 -0
  248. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab.egg-info/entry_points.txt +0 -0
  249. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab.egg-info/requires.txt +0 -0
  250. {handoverlab-2.4.0 → handoverlab-2.4.2}/src/handoverlab.egg-info/top_level.txt +0 -0
  251. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/conftest.py +0 -0
  252. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/data/bh6_reference.json +0 -0
  253. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/data/bh6_wide.json +0 -0
  254. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/data/make_bh6_reference.py +0 -0
  255. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/data/make_bh6_wide.py +0 -0
  256. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/data/public_api.json +0 -0
  257. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/helpers.py +0 -0
  258. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_ai_mobility.py +0 -0
  259. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_batch.py +0 -0
  260. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_beams_layers.py +0 -0
  261. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_buffers.py +0 -0
  262. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_calibration.py +0 -0
  263. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_channel_detail.py +0 -0
  264. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_cltm.py +0 -0
  265. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_config_cli.py +0 -0
  266. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_contract.py +0 -0
  267. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_determinism.py +0 -0
  268. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_dqn.py +0 -0
  269. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_engine_triggers.py +0 -0
  270. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_eventlog.py +0 -0
  271. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_fading.py +0 -0
  272. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_gui.py +0 -0
  273. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_highway.py +0 -0
  274. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_highway_tr37885.py +0 -0
  275. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_hst_dc.py +0 -0
  276. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_indoor_rural.py +0 -0
  277. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_invariants.py +0 -0
  278. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_levels_status_extend.py +0 -0
  279. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_lm_model.py +0 -0
  280. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_mapfile.py +0 -0
  281. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_measurement.py +0 -0
  282. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_mro.py +0 -0
  283. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_ntn.py +0 -0
  284. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_pathloss.py +0 -0
  285. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_protocol_3gpp.py +0 -0
  286. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_readme_boundaries.py +0 -0
  287. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_regression_bh6.py +0 -0
  288. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_regression_bh6_wide.py +0 -0
  289. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_rrc_detail.py +0 -0
  290. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_rules_rc2.py +0 -0
  291. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_scenarios.py +0 -0
  292. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_scenarios_230.py +0 -0
  293. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_sched_kernel.py +0 -0
  294. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_scheduler.py +0 -0
  295. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_signalling_energy.py +0 -0
  296. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_stability.py +0 -0
  297. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_stats.py +0 -0
  298. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_study.py +0 -0
  299. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_tools.py +0 -0
  300. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_traffic.py +0 -0
  301. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_tuning.py +0 -0
  302. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_ue_beams.py +0 -0
  303. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_v111.py +0 -0
  304. {handoverlab-2.4.0 → handoverlab-2.4.2}/tests/test_verify.py +0 -0
  305. {handoverlab-2.4.0 → handoverlab-2.4.2}/tools/compare_fingerprints.py +0 -0
  306. {handoverlab-2.4.0 → handoverlab-2.4.2}/tools/make_beam_figure.py +0 -0
  307. {handoverlab-2.4.0 → handoverlab-2.4.2}/tools/make_calibration_figure.py +0 -0
  308. {handoverlab-2.4.0 → handoverlab-2.4.2}/tools/make_ntn_figure.py +0 -0
  309. {handoverlab-2.4.0 → handoverlab-2.4.2}/tools/make_radiomap_figure.py +0 -0
  310. {handoverlab-2.4.0 → handoverlab-2.4.2}/tools/make_readme_images.py +0 -0
  311. {handoverlab-2.4.0 → handoverlab-2.4.2}/tools/mkdocs_hooks.py +0 -0
  312. {handoverlab-2.4.0 → handoverlab-2.4.2}/tools/release_check.py +0 -0
@@ -0,0 +1,39 @@
1
+ {
2
+ "title": "HandoverLab: system-level handover simulator for 5G-Advanced and beyond-5G research",
3
+ "description": "HandoverLab is an open-source, system-level simulator of 3GPP mobility procedures (baseline handover with Event A3, Release-16 conditional and DAPS handover, Release-18 L1/L2-triggered mobility, conditional handover with the location events of Release 18, dual connectivity) for many users in dense 5G-Advanced and beyond-5G networks, on a street grid, in an open area, along a highway or a high-speed railway, in an indoor office, in suburban and rural macro cells or under the earth-moving beams of a LEO satellite. It provides a TR 38.901 received-power radio model (TR 38.811 for the satellite) with optional TDL fast fading, SSB and UE receive beams and several carriers, an optional slot scheduler with MCS, TBS and HARQ and user-plane buffers at handover, an L3-filtered measurement chain, a radio-link failure model, an outcome label for every handover attempt, a plug-in interface for handover rules (including a measurement-prediction rule after TR 38.744), equal-budget tuning studies with paired statistics, and verification against hand-computed values, golden event-log fingerprints, the 3GPP large-scale calibration and ns-3 / 5G-LENA.",
4
+ "upload_type": "software",
5
+ "access_right": "open",
6
+ "license": "MIT",
7
+ "creators": [
8
+ {
9
+ "name": "Jalili Sanjarani, Mostafa"
10
+ },
11
+ {
12
+ "name": "Elmi Sola, Yasser"
13
+ }
14
+ ],
15
+ "keywords": [
16
+ "handover",
17
+ "conditional handover",
18
+ "mobility",
19
+ "mobility robustness",
20
+ "radio-link failure",
21
+ "system-level simulation",
22
+ "5G",
23
+ "beyond 5G",
24
+ "3GPP",
25
+ "Python",
26
+ "dual connectivity",
27
+ "fast fading",
28
+ "beam management",
29
+ "NTN",
30
+ "AI/ML mobility"
31
+ ],
32
+ "related_identifiers": [
33
+ {
34
+ "identifier": "https://github.com/mjs19971997/handoverlab",
35
+ "relation": "isSupplementTo",
36
+ "scheme": "url"
37
+ }
38
+ ]
39
+ }
@@ -7,6 +7,62 @@ All notable changes to this project are documented in this file. The format foll
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.4.2] - 2026-10-23
11
+
12
+ No change of results.
13
+
14
+ ### Added
15
+
16
+ - A picture for every option, each drawn from a real run by its own script in `tools/`: the handover
17
+ procedures side by side (`procedures.png`), mobility robustness optimisation (`mro.png`), fast fading
18
+ (`fading.png`), the slot scheduler with the Numba timings (`scheduler.png`), buffers at handover
19
+ (`buffers.png`), dual connectivity (`dual-connectivity.png`), UE receive beams (`ue-beams.png`) and the
20
+ traffic models (`traffic.png`); shown in the README and in each guide.
21
+ - `tools/make_dashboard_screenshots.py`: the dashboard screenshots taken with Edge through the DevTools
22
+ protocol; all four dashboard pictures redone with this version.
23
+
24
+ ### Fixed
25
+
26
+ - The speed-ups stated for 2.4.0 ("8 to 60" times, "50-80" times the rate model) were not all supported by the
27
+ measurements: `docs/performance.md` gives 23 to 59 times for the Numba scheduler and, measured again for 2.4.2
28
+ on the configuration of the scheduler picture, 42 (round robin) and 93 times (proportional fair), with the
29
+ NumPy scheduler about 91 times the rate model. The README, `docs/comparison.md`, the scheduler and fading guides
30
+ and `docs/performance.md` now give these measured numbers.
31
+
32
+ ### Documentation
33
+
34
+ - 7 GHz calibration: README, `docs/comparison.md`, `docs/calibration-3gpp.md` and
35
+ `docs/standard-compliance.md` say which cases they count (at 7 GHz 228 percentiles, largest distance
36
+ 1.69-2.43 dB; with the two 6 GHz reruns 342 percentiles, 1.65-2.88 dB).
37
+ - README model boundaries: the slot scheduler (2.2.0) and the user-plane buffers (2.3.0) listed as options,
38
+ with what is still not modelled.
39
+ - Scenario cards `suburban-sma-7ghz`, `rural-700mhz` and `indoor-office-4ghz`: the 7 GHz calibration of 2.4.0
40
+ and the hard-LOS results of `docs/guides/indoor-rural.md`; scenario pages regenerated.
41
+ - Examples rerun with this version and their numbers, and where needed their conclusions, updated: the guides
42
+ on buffers, MRO (the faster MRO setting is no better), beams and layers, indoor and rural scenarios, the
43
+ learning rule and fast fading; tutorial 2; the README traffic table; the `status` example in the user guide.
44
+ - User guide: all 15 cards, the `a3_pred` rule, `ttt_d2_s`, the layout kinds `indoor` and `ntn`, `run.backend`
45
+ under `run`, `ntn.hpbw_deg` (tabled widths at 2 GHz only), `ntn.los_model` and `radio.vegetation`; the study
46
+ example with a main guard. `docs/index.md`: the current layouts and cards. `docs/stability.md`: the missing
47
+ import. Tutorial 3: the cap of four extensions dates from 2.4.1.
48
+ - Citation with the DOI of 2.4.1.
49
+
50
+ ## [2.4.1] - 2026-10-22
51
+
52
+ No change of results.
53
+
54
+ ### Fixed
55
+
56
+ - `examples/study_smoke.yaml`: up to four grid extensions (`max_extensions: 4`); with two the example study
57
+ stopped at the `grid_edge` gate under the 3GPP defaults of 2.x.
58
+
59
+ ### Documentation
60
+
61
+ - README: pictures of the 7 GHz calibration, the new scenario cards and predicted measurements; what is new
62
+ in 2.1.0-2.4.0, the roadmap, the lower-layer options; the citation with the DOI of 2.4.0 and a BibTeX entry.
63
+ - `CITATION.cff` and `.zenodo.json`: description and keywords of the current features.
64
+ - Tutorials 1, 3 and 4 and the report pictures rerun with 2.4.0; status lines name the current release.
65
+
10
66
  ## [2.4.0] - 2026-10-22
11
67
 
12
68
  ### Added
@@ -1064,7 +1120,9 @@ First alpha release (stage 1: the core simulator).
1064
1120
  - Documentation: README, user guide, contribution guide, citation file; CI on Linux, Windows and
1065
1121
  macOS with Python 3.9-3.12.
1066
1122
 
1067
- [Unreleased]: https://github.com/mjs19971997/handoverlab/compare/v2.4.0...HEAD
1123
+ [Unreleased]: https://github.com/mjs19971997/handoverlab/compare/v2.4.2...HEAD
1124
+ [2.4.2]: https://github.com/mjs19971997/handoverlab/compare/v2.4.1...v2.4.2
1125
+ [2.4.1]: https://github.com/mjs19971997/handoverlab/compare/v2.4.0...v2.4.1
1068
1126
  [2.4.0]: https://github.com/mjs19971997/handoverlab/compare/v2.3.0...v2.4.0
1069
1127
  [2.3.0]: https://github.com/mjs19971997/handoverlab/compare/v2.2.0...v2.3.0
1070
1128
  [2.2.0]: https://github.com/mjs19971997/handoverlab/compare/v2.1.0...v2.2.0
@@ -6,12 +6,15 @@ abstract: >-
6
6
  handover with Event A3, Release-16 conditional and DAPS handover, Release-18 L1/L2-triggered
7
7
  mobility, conditional handover with the location events of Release 18) for many users in dense
8
8
  5G and beyond-5G networks, on a street grid, in an open area, along a highway, indoors, in rural
9
- cells or under the earth-moving beams of a LEO satellite. It provides a TR 38.901 received-power
10
- radio model (TR 38.811 for the satellite), an L3-filtered
11
- measurement chain, a radio-link failure model, an outcome label for every handover attempt,
12
- a plug-in interface for handover rules, equal-budget tuning studies with paired statistics,
13
- and verification against hand-computed values, golden event-log fingerprints and ns-3 / 5G-LENA.
14
- version: "2.4.0"
9
+ cells, along a high-speed railway or under the earth-moving beams of a LEO satellite. It provides a
10
+ TR 38.901 received-power radio model (TR 38.811 for the satellite) with optional TDL fast fading,
11
+ SSB and UE receive beams, several carriers and dual connectivity, an optional slot scheduler with
12
+ MCS, TBS and HARQ and user-plane buffers at handover, an L3-filtered measurement chain, a
13
+ radio-link failure model, an outcome label for every handover attempt, a plug-in interface for
14
+ handover rules (including a measurement-prediction rule after TR 38.744), equal-budget tuning
15
+ studies with paired statistics, and verification against hand-computed values, golden event-log
16
+ fingerprints, the 3GPP large-scale calibration and ns-3 / 5G-LENA.
17
+ version: "2.4.2"
15
18
  doi: 10.5281/zenodo.23409131
16
19
  identifiers:
17
20
  - type: doi
@@ -23,7 +26,13 @@ identifiers:
23
26
  - type: doi
24
27
  value: 10.5281/zenodo.23409402
25
28
  description: "Version 1.0.1 on Zenodo"
26
- date-released: 2026-10-22
29
+ - type: doi
30
+ value: 10.5281/zenodo.23582521
31
+ description: "Version 2.4.0 on Zenodo"
32
+ - type: doi
33
+ value: 10.5281/zenodo.23585308
34
+ description: "Version 2.4.1 on Zenodo"
35
+ date-released: 2026-10-23
27
36
  license: MIT
28
37
  repository-code: "https://github.com/mjs19971997/handoverlab"
29
38
  url: "https://mjs19971997.github.io/handoverlab/"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: handoverlab
3
- Version: 2.4.0
3
+ Version: 2.4.2
4
4
  Summary: System-level handover simulator for 5G-Advanced and beyond-5G research
5
5
  Author: Mostafa Jalili Sanjarani, Yasser Elmi Sola
6
6
  License-Expression: MIT
@@ -70,7 +70,7 @@ received-power-level radio model from TR 38.901 (TR 38.811 for the satellite) (o
70
70
  and several carriers), an L3-filtered measurement chain, a radio-link failure model, and an
71
71
  outcome label for every handover attempt.
72
72
 
73
- > **Status: 2.0.0** (`python -m pip install handoverlab`). The public surface (configuration and
73
+ > **Status: 2.4.2** (`python -m pip install handoverlab`). The public surface (configuration and
74
74
  > result formats with a schema version, the rule interface, metric names, commands and the
75
75
  > documented Python names) follows the [stability policy](https://github.com/mjs19971997/handoverlab/blob/main/docs/stability.md): within 2.x it only grows,
76
76
  > and anything removed is deprecated first. 2.0.0 makes the 3GPP values the defaults (the protocol profile,
@@ -137,6 +137,60 @@ event D2 of Release 18:
137
137
 
138
138
  ![The 19 beams on the ground at the start and end of a run, and the received power of each beam at one user](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/ntn-beams.png)
139
139
 
140
+ **New cards.** Since 2.3.0: the TR 37.885 urban grid with 35 macro sites 500 m apart (4 GHz), suburban
141
+ macro (SMa) at 7 GHz with 11 sites 1299 m apart and 80 % of the users indoors, and a high-speed train in FR2
142
+ (TR 38.854: 12 remote radio heads 700 m apart, 10 m from the track, 350 km/h):
143
+
144
+ ![Layouts of the cards urban-macro-tr37885-4ghz, suburban-sma-7ghz and hst-fr2-28ghz](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/new-scenarios.png)
145
+
146
+ **Predicted measurements.** Since 2.4.0 the rule `a3_pred` hands over on predicted L3 results, as studied
147
+ in TR 38.744. Trained on two seeds and tested on two others, the ridge predictor is about 0.5-0.6 dB more
148
+ accurate than sample and hold 400 ms ahead (1.84 / 2.66 / 3.14 dB against 2.38 / 3.26 / 3.74 dB at 30 / 60 /
149
+ 90 km/h):
150
+
151
+ ![Prediction error against horizon for the ridge predictor and sample and hold at 30, 60 and 90 km/h](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/ai-mobility.png)
152
+
153
+ **Handover procedures side by side.** On one card failures fall from 0.6 (A3) to 0.2 (LTM and CLTM) per
154
+ UE-minute; DAPS has no execution interruption; LTM pays with 192 RRC messages per UE-minute against 45 for A3:
155
+
156
+ ![Failures and ping-pong, interruption and RRC messages for A3, CHO, DAPS, LTM and CLTM](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/procedures.png)
157
+
158
+ **Mobility robustness optimisation.** `a3_mro` moves the offset of every cell pair from its own failures;
159
+ here 17 pairs move and failures fall from 0.22 to 0.14 per UE-minute when starting from 3 dB:
160
+
161
+ ![Cell-pair offsets over time under a3_mro, and failures against fixed A3](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/mro.png)
162
+
163
+ **Fast fading.** With TDL-A or TDL-C the 5th percentile of the link-monitoring SINR on the ns-3 card falls
164
+ from 8.3 dB to 3.8 and 3.4 dB:
165
+
166
+ ![Received power of one vehicle with no fading, TDL-A and TDL-C, and the distribution of the link-monitoring SINR](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/fading.png)
167
+
168
+ **Slot scheduler.** Round robin and proportional fair with the MCS, TBS and HARQ of TS 38.214; with
169
+ `run.backend: numba` the same runs take 2.2 s and 1.0 s instead of 92.7 s and 93.3 s with NumPy, with identical
170
+ fingerprints (the default rate model takes about 1.0 s for the same run):
171
+
172
+ ![Delivered rate of each vehicle against its SINR for round robin and proportional fair, and the wall time with NumPy and Numba](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/scheduler.png)
173
+
174
+ **Buffers at handover.** Without data forwarding A3 loses 2.17 % of the data and DAPS 0.34 %; with
175
+ forwarding nothing is lost, and the forwarded data wait 85-349 ms:
176
+
177
+ ![Lost data with and without forwarding, and the PDCP delay, for A3, CHO, DAPS and LTM](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/buffers.png)
178
+
179
+ **Dual connectivity.** A 4 GHz master cell and a 30 GHz secondary cell: the secondary cell group carries data
180
+ 96 % of the time and 183 Mbit/s per user, against 10.1 Mbit/s on the master cell group:
181
+
182
+ ![One user's 4 GHz master cell and 30 GHz secondary cell over time with the dual-connectivity events, and the procedure rates](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/dual-connectivity.png)
183
+
184
+ **UE receive beams.** Two panels with DFT beams (peak gain 13.7 dBi) raise the mean SINR from 10.9 to 19.2 dB
185
+ and cut failures from 3.60 to 1.44 per UE-minute; a beam sweep keeps them at 3.36:
186
+
187
+ ![Receive beam patterns of a two-panel UE, and SINR and failures for four UE receive-beam setups](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/ue-beams.png)
188
+
189
+ **Traffic models.** The same handovers (11.3 per UE-minute) under fixed rates, full buffer, periodic packets and FTP model 3,
190
+ with very different rate, cell load and energy per bit:
191
+
192
+ ![Rate, cell load and energy per bit for the four traffic models](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/traffic.png)
193
+
140
194
  ## What it models
141
195
 
142
196
  - **Scenarios**: the TR 37.885 urban street grid (configurable number of blocks; 433 m x 250 m
@@ -155,7 +209,11 @@ event D2 of Release 18:
155
209
  - **Beams and carriers** (options, 1.10.0): sectors with SSB beams from the TR 38.901 antenna
156
210
  model, cell quality from the beams (TS 38.331 5.5.3.3), the serving beam from beam reports, beam
157
211
  failure detection and recovery (TS 38.321 5.17, TS 38.133 8.5), several carriers with the
158
- measurement periods and gaps of TS 38.133, Event A5 between carriers.
212
+ measurement periods and gaps of TS 38.133, Event A5 between carriers; UE receive beams (since 2.4.0) and
213
+ dual connectivity with a secondary cell group (since 2.3.0, TS 37.340).
214
+ - **Lower layers** (options, since 2.2.0): TDL fast fading of TR 38.901 with an effective SINR (MIESM) for
215
+ link monitoring and the rate; a slot scheduler with the MCS, TBS and HARQ of TS 38.214; user-plane buffers
216
+ at handover with data forwarding (since 2.3.0, TS 38.300, TS 38.322, TS 38.323).
159
217
  - **Mobility**: street-following users with turn probabilities, random waypoints in the open area,
160
218
  pedestrian and vehicular speed profiles (by default the urban vehicles of TR 37.885: 60 km/h in one of
161
219
  two lanes) or your own speed groups.
@@ -172,7 +230,8 @@ event D2 of Release 18:
172
230
  epsilon-greedy bandit (`a3_bandit`, checked against an exhaustive search) and a deep Q-network
173
231
  (`dqn`, optional PyTorch).
174
232
  - **Failure model**: Qout/Qin with windows, N310/N311/T310, T304, lost commands and configurations,
175
- execution failures, re-establishment after a fixed outage (1 s, an assumption), the handover command
233
+ execution failures, re-establishment after a fixed outage (1 s, inside the bounds of TS 38.133
234
+ 6.2.1.2.1), the handover command
176
235
  during T310 as TS 38.331 specifies and the restart of the link monitoring on a new cell as HandoverLab
177
236
  reads TS 38.133 8.1.2.2 (defaults since 2.0.0), with options for the link monitoring (own interferer load, ideal random access).
178
237
  - **Metrics**: outcome of every attempt (useful, unnecessary, too early, wrong cell, too late,
@@ -195,7 +254,7 @@ the clause-by-clause detail is in [standard compliance](https://github.com/mjs19
195
254
  | Channel | TR 38.901 path loss and LOS (UMi, UMa, RMa, SMa, InH), LOS from buildings, spatially consistent LOS and shadowing, car and O2I building penetration loss, radio maps from a file (clause 8), TR 38.811 for the satellite | received power per site and step with a slow time-varying component; indoor users keep the LOS state and shadowing of their position; optional TDL fast fading with effective SINRs (clause 7.7.2, since 2.2.0) | CDL and the full fast-fading model of clause 7.5, MIMO |
196
255
  | Beams and carriers | SSB beams per sector, cell quality from beams, beam failure detection and recovery, several carriers with gaps and Event A5; dual connectivity (NR-DC: SN addition, PSCell change, SN release, SCG failure; option since 2.3.0) | the TR 38.901 antenna element and DFT beams; isotropic UE unless UE receive panels are set (option since 2.4.0); the SCG as one PSCell with a full-buffer share | UE transmit beams and polarisation, conditional PSCell change, fast MCG recovery |
197
256
  | Mobility | street-following vehicles (60 km/h, two lanes), highway lanes at 70/140 km/h, a train at 350 km/h (TR 38.854), random waypoints, pedestrians | constant speed per user | handheld rotation and body blockage |
198
- | Traffic and load | constant rates per 5QI, full buffer, periodic, FTP model 3; cell load drives interference | rate from SINR (Shannon-type mapping), no scheduler | slot scheduler, HARQ, RLC/PDCP, TCP and applications |
257
+ | Traffic and load | constant rates per 5QI, full buffer, periodic, FTP model 3; cell load drives interference; options: a slot scheduler (`protocol.scheduler`: round robin or proportional fair) with the MCS, TBS and HARQ of TS 38.214 (since 2.2.0), and user-plane buffers at handover (`protocol.buffers`: simplified PDCP / RLC in AM or UM with Xn data forwarding, since 2.3.0) | by default the rate from the SINR (Shannon-type mapping) without a scheduler; with the scheduler the channel is held for the 10 ms step and the MCS is chosen from the SINR of one measurement interval earlier (no CSI reports); buffers: downlink only, one bearer per user, the interruption quantised to the measurement interval; both options need the base engine (no beams, layers, NTN or TS 38.133 periods) | uplink data, CSI-based link adaptation, PDCP reordering and status reports at the UE, TCP and applications |
199
258
  | Measurements | L1 samples with error, TS 38.331 L3 filter, TS 38.133 measurement periods and gaps (option) | wideband RSRP; SS-RSRP per resource element with beams/carriers | RSRQ, CSI reporting |
200
259
  | Procedures | baseline (A3), CHO, DAPS, LTM, conditional LTM, CHO with D1/D2 for satellites, A3/A5 between carriers; rules `a3`, `a3a5`, `a3_mro`, `a3_bandit`, `dqn`, `a3_pred`, `cho`, `cho_d2`, `daps`, `ltm`, `cltm` | fixed preparation, command and execution delays; re-establishment always succeeds after a fixed outage | condEventT1, RACH-less NTN handover, Xn signalling in detail |
201
260
  | Failure model | Qout/Qin with windows, N310/N311/T310, T304, command received during T310, re-establishment, link-monitoring restart | Qout/Qin as SINR thresholds (TR 36.839 values) instead of the BLER of a hypothetical PDCCH | BLER-based link monitoring; absolute failure rates are not calibrated: compare rules with each other |
@@ -235,7 +294,13 @@ range of the 21 companies that reported their results in the 3GPP contribution R
235
294
  Ericsson, Nokia, Samsung, Qualcomm and others), for UMa, UMi and the indoor office at 6 and
236
295
  30 GHz. 325 of 342 compared percentiles are inside the range, none is more than about 1 dB from
237
296
  the industry mean, and `handoverlab verify` repeats the check
238
- ([details](https://github.com/mjs19971997/handoverlab/blob/main/docs/calibration-3gpp.md)).
297
+ ([details](https://github.com/mjs19971997/handoverlab/blob/main/docs/calibration-3gpp.md)). Since 2.4.0 the
298
+ same check runs for Table 7.8-1A against the companies of R1-2506406. At 7 GHz (UMa, UMi and SMa with ISD
299
+ 1299 m and 1732 m) all 228 percentiles lie inside their range, but the largest distance from their mean is
300
+ 1.69-2.43 dB, which misses the 1.5 dB criterion set before the run; the two 6 GHz reruns of UMa and UMi with
301
+ the updated model add 114 percentiles, also all inside, at 1.65 and 2.88 dB.
302
+
303
+ ![CDFs of coupling loss and geometry for UMa, UMi and SMa at 7 GHz, with the HandoverLab curve inside the company range of R1-2506406](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/calibration_7ghz.png)
239
304
 
240
305
  ![HandoverLab against the 21 companies of 3GPP R1-165974](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/calibration_38901.png)
241
306
 
@@ -280,6 +345,20 @@ L1/L2-triggered mobility.
280
345
 
281
346
  ## What's new
282
347
 
348
+ - **2.4.0**: UE receive beams (panels of TR 38.802, best beam or a sweep); a measurement-prediction rule after
349
+ TR 38.744 (`a3_pred`: predicted Event A3 or measurement skipping, sample and hold or a trained ridge
350
+ predictor); the slot scheduler as a compiled kernel (`run.backend: numba`, bit-identical; on the ns-3 card
351
+ 42 times (`rr`) and 93 times (`pf`) faster than the NumPy loop); the 7 GHz large-scale calibration against the companies of R1-2506406 (every percentile inside the
352
+ range, the distance to the mean criterion missed); a [comparison with other simulators](https://github.com/mjs19971997/handoverlab/blob/main/docs/comparison.md).
353
+ - **2.3.0**: user-plane buffers at handover (PDCP / RLC, Xn data forwarding for baseline, conditional, DAPS and
354
+ L1/L2-triggered handover); the TR 37.885 urban macro grid, suburban macro (SMa) and O2I penetration of indoor
355
+ users; a high-speed train card from TR 38.854; dual connectivity (TS 37.340: SN addition, PSCell change, SN
356
+ release, SCG failure); a fresh held-out check of the failure model against new ns-3 runs, reported as it
357
+ came.
358
+ - **2.2.0**: TDL fast fading of TR 38.901 with an effective SINR for link monitoring and rate; a slot scheduler
359
+ with the MCS, TBS and HARQ of TS 38.214; checked against ns-3 runs with fading.
360
+ - **2.1.0**: a clause-by-clause audit against the full 3GPP texts (`protocol.rrc_detail`,
361
+ `radio.channel_detail`), value domains from the standards and a study gate that checks them.
283
362
  - **2.0.0**: satellites (non-terrestrial networks): one LEO satellite at 600 km with 19 earth-moving beams
284
363
  (TR 38.811 channel, TR 38.821 Set-1 S band), conditional handover with the location event D2 of TS 38.331
285
364
  Release 18 (`cho_d2`), checked against the link budgets of TR 38.821 (within 0.03 dB). The 3GPP values
@@ -400,13 +479,13 @@ traffic models (one seed, 30 users, 60 s on the urban grid at 10 GHz):
400
479
 
401
480
  ```text
402
481
  model cell load rate [Mbit/s] delivered SINR [dB] failures/UE-min
403
- fixed 0.28 14.25 0.98 24.3 0.12
404
- full_buffer 0.52 725.93 0.49 21.9 0.08
405
- periodic 0.28 0.04 0.80 24.4 0.12
406
- ftp3 0.28 3.93 0.85 24.4 0.12
482
+ fixed 0.28 14.10 0.97 23.6 0.08
483
+ full_buffer 0.52 717.77 0.48 21.2 0.08
484
+ periodic 0.28 0.04 0.86 23.7 0.08
485
+ ftp3 0.28 3.93 0.87 23.7 0.08
407
486
  ```
408
487
 
409
- Busier cells interfere more: under full buffer the SINR drops by about 2.5 dB. With one seed each
488
+ Busier cells interfere more: under full buffer the SINR drops by about 2.4 dB. With one seed each
410
489
  failure rate counts only a few failures; compare them over several seeds.
411
490
 
412
491
  The full script is [examples/compare_a3_cho.py](https://github.com/mjs19971997/handoverlab/blob/main/examples/compare_a3_cho.py). Writing your own
@@ -480,19 +559,44 @@ the pages are plain Markdown in [docs/](https://github.com/mjs19971997/handoverl
480
559
  20. 1.11.0: the TR 37.885 highway, the card audit, the bandit against an exhaustive search, the
481
560
  `dqn` rule and the optional Numba kernel.
482
561
  21. 1.12.0: radio maps from ray tracing or measurements.
483
- 22. **2.0.0 (this release)**: a LEO satellite with earth-moving beams and conditional handover with
562
+ 22. 2.0.0: a LEO satellite with earth-moving beams and conditional handover with
484
563
  event D2; the 3GPP values as defaults, with a switch back to 1.x.
485
- 23. Later (planned, not done): the failure model checked on held-out measurements, the sensitivity of
486
- the results to the time step (LTM and beams), a reproducible benchmark package against
487
- ns-3 / 5G-LENA, a table of model boundaries, condEventT1 and earth-fixed beams.
564
+ 23. 2.1.0: the clause-by-clause standard audit; held-out validation of the failure model, the
565
+ time-step study, the ns-3 benchmark package and the table of model boundaries.
566
+ 24. 2.2.0: fast fading with link-to-system mapping; the slot scheduler with MCS, TBS and HARQ.
567
+ 25. 2.3.0: buffers at handover, urban macro, SMa and O2I, the high-speed train, dual connectivity.
568
+ 26. 2.4.0: UE receive beams, the TR 38.744 prediction rule, the compiled
569
+ scheduler, the 7 GHz calibration and the comparison with other simulators.
570
+ 27. 2.4.1: pictures, citation and tutorials brought up to date; the example study
571
+ completes again; no change of results.
572
+ 28. **2.4.2 (this release)**: every option has a picture; the dashboard pictures show the current version;
573
+ guide and tutorial examples rerun; facts made consistent; no change of results.
574
+ 29. Later (planned, not done), staying a handover simulator: the effect of a handover on what the user
575
+ sees (simple TCP and application models on top of the buffers), MIMO as an SINR gain, hundreds of
576
+ users per run, and one scenario definition that also runs in ns-3; condEventT1 and earth-fixed beams.
488
577
 
489
578
  ## Citation
490
579
 
491
580
  If you use HandoverLab, please cite it as described in [CITATION.cff](https://github.com/mjs19971997/handoverlab/blob/main/CITATION.cff) (GitHub shows
492
- it under *Cite this repository*). The releases are archived on Zenodo:
581
+ it under *Cite this repository*). Every release is archived on Zenodo:
493
582
  [doi:10.5281/zenodo.23409131](https://doi.org/10.5281/zenodo.23409131) cites all versions (it resolves to
494
- the latest); version 1.0.0 is [doi:10.5281/zenodo.23409132](https://doi.org/10.5281/zenodo.23409132)
495
- and version 1.0.1 [doi:10.5281/zenodo.23409402](https://doi.org/10.5281/zenodo.23409402).
583
+ the latest). To cite the exact version you used, take its DOI from the version list on that page, where
584
+ the DOI of the latest version is listed; for example, version 2.4.1 is
585
+ [doi:10.5281/zenodo.23585308](https://doi.org/10.5281/zenodo.23585308) and version 2.4.0
586
+ [doi:10.5281/zenodo.23582521](https://doi.org/10.5281/zenodo.23582521). The BibTeX entry below cites 2.4.1;
587
+ replace version and DOI with those of the version you used.
588
+
589
+ ```bibtex
590
+ @software{handoverlab,
591
+ author = {Jalili Sanjarani, Mostafa and Elmi Sola, Yasser},
592
+ title = {{HandoverLab}: system-level handover simulator for 5G-Advanced and beyond-5G research},
593
+ year = {2026},
594
+ publisher = {Zenodo},
595
+ version = {2.4.1},
596
+ doi = {10.5281/zenodo.23585308},
597
+ url = {https://github.com/mjs19971997/handoverlab}
598
+ }
599
+ ```
496
600
 
497
601
  ## Licence
498
602
 
@@ -12,7 +12,7 @@ received-power-level radio model from TR 38.901 (TR 38.811 for the satellite) (o
12
12
  and several carriers), an L3-filtered measurement chain, a radio-link failure model, and an
13
13
  outcome label for every handover attempt.
14
14
 
15
- > **Status: 2.0.0** (`python -m pip install handoverlab`). The public surface (configuration and
15
+ > **Status: 2.4.2** (`python -m pip install handoverlab`). The public surface (configuration and
16
16
  > result formats with a schema version, the rule interface, metric names, commands and the
17
17
  > documented Python names) follows the [stability policy](https://github.com/mjs19971997/handoverlab/blob/main/docs/stability.md): within 2.x it only grows,
18
18
  > and anything removed is deprecated first. 2.0.0 makes the 3GPP values the defaults (the protocol profile,
@@ -79,6 +79,60 @@ event D2 of Release 18:
79
79
 
80
80
  ![The 19 beams on the ground at the start and end of a run, and the received power of each beam at one user](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/ntn-beams.png)
81
81
 
82
+ **New cards.** Since 2.3.0: the TR 37.885 urban grid with 35 macro sites 500 m apart (4 GHz), suburban
83
+ macro (SMa) at 7 GHz with 11 sites 1299 m apart and 80 % of the users indoors, and a high-speed train in FR2
84
+ (TR 38.854: 12 remote radio heads 700 m apart, 10 m from the track, 350 km/h):
85
+
86
+ ![Layouts of the cards urban-macro-tr37885-4ghz, suburban-sma-7ghz and hst-fr2-28ghz](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/new-scenarios.png)
87
+
88
+ **Predicted measurements.** Since 2.4.0 the rule `a3_pred` hands over on predicted L3 results, as studied
89
+ in TR 38.744. Trained on two seeds and tested on two others, the ridge predictor is about 0.5-0.6 dB more
90
+ accurate than sample and hold 400 ms ahead (1.84 / 2.66 / 3.14 dB against 2.38 / 3.26 / 3.74 dB at 30 / 60 /
91
+ 90 km/h):
92
+
93
+ ![Prediction error against horizon for the ridge predictor and sample and hold at 30, 60 and 90 km/h](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/ai-mobility.png)
94
+
95
+ **Handover procedures side by side.** On one card failures fall from 0.6 (A3) to 0.2 (LTM and CLTM) per
96
+ UE-minute; DAPS has no execution interruption; LTM pays with 192 RRC messages per UE-minute against 45 for A3:
97
+
98
+ ![Failures and ping-pong, interruption and RRC messages for A3, CHO, DAPS, LTM and CLTM](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/procedures.png)
99
+
100
+ **Mobility robustness optimisation.** `a3_mro` moves the offset of every cell pair from its own failures;
101
+ here 17 pairs move and failures fall from 0.22 to 0.14 per UE-minute when starting from 3 dB:
102
+
103
+ ![Cell-pair offsets over time under a3_mro, and failures against fixed A3](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/mro.png)
104
+
105
+ **Fast fading.** With TDL-A or TDL-C the 5th percentile of the link-monitoring SINR on the ns-3 card falls
106
+ from 8.3 dB to 3.8 and 3.4 dB:
107
+
108
+ ![Received power of one vehicle with no fading, TDL-A and TDL-C, and the distribution of the link-monitoring SINR](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/fading.png)
109
+
110
+ **Slot scheduler.** Round robin and proportional fair with the MCS, TBS and HARQ of TS 38.214; with
111
+ `run.backend: numba` the same runs take 2.2 s and 1.0 s instead of 92.7 s and 93.3 s with NumPy, with identical
112
+ fingerprints (the default rate model takes about 1.0 s for the same run):
113
+
114
+ ![Delivered rate of each vehicle against its SINR for round robin and proportional fair, and the wall time with NumPy and Numba](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/scheduler.png)
115
+
116
+ **Buffers at handover.** Without data forwarding A3 loses 2.17 % of the data and DAPS 0.34 %; with
117
+ forwarding nothing is lost, and the forwarded data wait 85-349 ms:
118
+
119
+ ![Lost data with and without forwarding, and the PDCP delay, for A3, CHO, DAPS and LTM](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/buffers.png)
120
+
121
+ **Dual connectivity.** A 4 GHz master cell and a 30 GHz secondary cell: the secondary cell group carries data
122
+ 96 % of the time and 183 Mbit/s per user, against 10.1 Mbit/s on the master cell group:
123
+
124
+ ![One user's 4 GHz master cell and 30 GHz secondary cell over time with the dual-connectivity events, and the procedure rates](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/dual-connectivity.png)
125
+
126
+ **UE receive beams.** Two panels with DFT beams (peak gain 13.7 dBi) raise the mean SINR from 10.9 to 19.2 dB
127
+ and cut failures from 3.60 to 1.44 per UE-minute; a beam sweep keeps them at 3.36:
128
+
129
+ ![Receive beam patterns of a two-panel UE, and SINR and failures for four UE receive-beam setups](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/ue-beams.png)
130
+
131
+ **Traffic models.** The same handovers (11.3 per UE-minute) under fixed rates, full buffer, periodic packets and FTP model 3,
132
+ with very different rate, cell load and energy per bit:
133
+
134
+ ![Rate, cell load and energy per bit for the four traffic models](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/traffic.png)
135
+
82
136
  ## What it models
83
137
 
84
138
  - **Scenarios**: the TR 37.885 urban street grid (configurable number of blocks; 433 m x 250 m
@@ -97,7 +151,11 @@ event D2 of Release 18:
97
151
  - **Beams and carriers** (options, 1.10.0): sectors with SSB beams from the TR 38.901 antenna
98
152
  model, cell quality from the beams (TS 38.331 5.5.3.3), the serving beam from beam reports, beam
99
153
  failure detection and recovery (TS 38.321 5.17, TS 38.133 8.5), several carriers with the
100
- measurement periods and gaps of TS 38.133, Event A5 between carriers.
154
+ measurement periods and gaps of TS 38.133, Event A5 between carriers; UE receive beams (since 2.4.0) and
155
+ dual connectivity with a secondary cell group (since 2.3.0, TS 37.340).
156
+ - **Lower layers** (options, since 2.2.0): TDL fast fading of TR 38.901 with an effective SINR (MIESM) for
157
+ link monitoring and the rate; a slot scheduler with the MCS, TBS and HARQ of TS 38.214; user-plane buffers
158
+ at handover with data forwarding (since 2.3.0, TS 38.300, TS 38.322, TS 38.323).
101
159
  - **Mobility**: street-following users with turn probabilities, random waypoints in the open area,
102
160
  pedestrian and vehicular speed profiles (by default the urban vehicles of TR 37.885: 60 km/h in one of
103
161
  two lanes) or your own speed groups.
@@ -114,7 +172,8 @@ event D2 of Release 18:
114
172
  epsilon-greedy bandit (`a3_bandit`, checked against an exhaustive search) and a deep Q-network
115
173
  (`dqn`, optional PyTorch).
116
174
  - **Failure model**: Qout/Qin with windows, N310/N311/T310, T304, lost commands and configurations,
117
- execution failures, re-establishment after a fixed outage (1 s, an assumption), the handover command
175
+ execution failures, re-establishment after a fixed outage (1 s, inside the bounds of TS 38.133
176
+ 6.2.1.2.1), the handover command
118
177
  during T310 as TS 38.331 specifies and the restart of the link monitoring on a new cell as HandoverLab
119
178
  reads TS 38.133 8.1.2.2 (defaults since 2.0.0), with options for the link monitoring (own interferer load, ideal random access).
120
179
  - **Metrics**: outcome of every attempt (useful, unnecessary, too early, wrong cell, too late,
@@ -137,7 +196,7 @@ the clause-by-clause detail is in [standard compliance](https://github.com/mjs19
137
196
  | Channel | TR 38.901 path loss and LOS (UMi, UMa, RMa, SMa, InH), LOS from buildings, spatially consistent LOS and shadowing, car and O2I building penetration loss, radio maps from a file (clause 8), TR 38.811 for the satellite | received power per site and step with a slow time-varying component; indoor users keep the LOS state and shadowing of their position; optional TDL fast fading with effective SINRs (clause 7.7.2, since 2.2.0) | CDL and the full fast-fading model of clause 7.5, MIMO |
138
197
  | Beams and carriers | SSB beams per sector, cell quality from beams, beam failure detection and recovery, several carriers with gaps and Event A5; dual connectivity (NR-DC: SN addition, PSCell change, SN release, SCG failure; option since 2.3.0) | the TR 38.901 antenna element and DFT beams; isotropic UE unless UE receive panels are set (option since 2.4.0); the SCG as one PSCell with a full-buffer share | UE transmit beams and polarisation, conditional PSCell change, fast MCG recovery |
139
198
  | Mobility | street-following vehicles (60 km/h, two lanes), highway lanes at 70/140 km/h, a train at 350 km/h (TR 38.854), random waypoints, pedestrians | constant speed per user | handheld rotation and body blockage |
140
- | Traffic and load | constant rates per 5QI, full buffer, periodic, FTP model 3; cell load drives interference | rate from SINR (Shannon-type mapping), no scheduler | slot scheduler, HARQ, RLC/PDCP, TCP and applications |
199
+ | Traffic and load | constant rates per 5QI, full buffer, periodic, FTP model 3; cell load drives interference; options: a slot scheduler (`protocol.scheduler`: round robin or proportional fair) with the MCS, TBS and HARQ of TS 38.214 (since 2.2.0), and user-plane buffers at handover (`protocol.buffers`: simplified PDCP / RLC in AM or UM with Xn data forwarding, since 2.3.0) | by default the rate from the SINR (Shannon-type mapping) without a scheduler; with the scheduler the channel is held for the 10 ms step and the MCS is chosen from the SINR of one measurement interval earlier (no CSI reports); buffers: downlink only, one bearer per user, the interruption quantised to the measurement interval; both options need the base engine (no beams, layers, NTN or TS 38.133 periods) | uplink data, CSI-based link adaptation, PDCP reordering and status reports at the UE, TCP and applications |
141
200
  | Measurements | L1 samples with error, TS 38.331 L3 filter, TS 38.133 measurement periods and gaps (option) | wideband RSRP; SS-RSRP per resource element with beams/carriers | RSRQ, CSI reporting |
142
201
  | Procedures | baseline (A3), CHO, DAPS, LTM, conditional LTM, CHO with D1/D2 for satellites, A3/A5 between carriers; rules `a3`, `a3a5`, `a3_mro`, `a3_bandit`, `dqn`, `a3_pred`, `cho`, `cho_d2`, `daps`, `ltm`, `cltm` | fixed preparation, command and execution delays; re-establishment always succeeds after a fixed outage | condEventT1, RACH-less NTN handover, Xn signalling in detail |
143
202
  | Failure model | Qout/Qin with windows, N310/N311/T310, T304, command received during T310, re-establishment, link-monitoring restart | Qout/Qin as SINR thresholds (TR 36.839 values) instead of the BLER of a hypothetical PDCCH | BLER-based link monitoring; absolute failure rates are not calibrated: compare rules with each other |
@@ -177,7 +236,13 @@ range of the 21 companies that reported their results in the 3GPP contribution R
177
236
  Ericsson, Nokia, Samsung, Qualcomm and others), for UMa, UMi and the indoor office at 6 and
178
237
  30 GHz. 325 of 342 compared percentiles are inside the range, none is more than about 1 dB from
179
238
  the industry mean, and `handoverlab verify` repeats the check
180
- ([details](https://github.com/mjs19971997/handoverlab/blob/main/docs/calibration-3gpp.md)).
239
+ ([details](https://github.com/mjs19971997/handoverlab/blob/main/docs/calibration-3gpp.md)). Since 2.4.0 the
240
+ same check runs for Table 7.8-1A against the companies of R1-2506406. At 7 GHz (UMa, UMi and SMa with ISD
241
+ 1299 m and 1732 m) all 228 percentiles lie inside their range, but the largest distance from their mean is
242
+ 1.69-2.43 dB, which misses the 1.5 dB criterion set before the run; the two 6 GHz reruns of UMa and UMi with
243
+ the updated model add 114 percentiles, also all inside, at 1.65 and 2.88 dB.
244
+
245
+ ![CDFs of coupling loss and geometry for UMa, UMi and SMa at 7 GHz, with the HandoverLab curve inside the company range of R1-2506406](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/calibration_7ghz.png)
181
246
 
182
247
  ![HandoverLab against the 21 companies of 3GPP R1-165974](https://raw.githubusercontent.com/mjs19971997/handoverlab/main/docs/images/calibration_38901.png)
183
248
 
@@ -222,6 +287,20 @@ L1/L2-triggered mobility.
222
287
 
223
288
  ## What's new
224
289
 
290
+ - **2.4.0**: UE receive beams (panels of TR 38.802, best beam or a sweep); a measurement-prediction rule after
291
+ TR 38.744 (`a3_pred`: predicted Event A3 or measurement skipping, sample and hold or a trained ridge
292
+ predictor); the slot scheduler as a compiled kernel (`run.backend: numba`, bit-identical; on the ns-3 card
293
+ 42 times (`rr`) and 93 times (`pf`) faster than the NumPy loop); the 7 GHz large-scale calibration against the companies of R1-2506406 (every percentile inside the
294
+ range, the distance to the mean criterion missed); a [comparison with other simulators](https://github.com/mjs19971997/handoverlab/blob/main/docs/comparison.md).
295
+ - **2.3.0**: user-plane buffers at handover (PDCP / RLC, Xn data forwarding for baseline, conditional, DAPS and
296
+ L1/L2-triggered handover); the TR 37.885 urban macro grid, suburban macro (SMa) and O2I penetration of indoor
297
+ users; a high-speed train card from TR 38.854; dual connectivity (TS 37.340: SN addition, PSCell change, SN
298
+ release, SCG failure); a fresh held-out check of the failure model against new ns-3 runs, reported as it
299
+ came.
300
+ - **2.2.0**: TDL fast fading of TR 38.901 with an effective SINR for link monitoring and rate; a slot scheduler
301
+ with the MCS, TBS and HARQ of TS 38.214; checked against ns-3 runs with fading.
302
+ - **2.1.0**: a clause-by-clause audit against the full 3GPP texts (`protocol.rrc_detail`,
303
+ `radio.channel_detail`), value domains from the standards and a study gate that checks them.
225
304
  - **2.0.0**: satellites (non-terrestrial networks): one LEO satellite at 600 km with 19 earth-moving beams
226
305
  (TR 38.811 channel, TR 38.821 Set-1 S band), conditional handover with the location event D2 of TS 38.331
227
306
  Release 18 (`cho_d2`), checked against the link budgets of TR 38.821 (within 0.03 dB). The 3GPP values
@@ -342,13 +421,13 @@ traffic models (one seed, 30 users, 60 s on the urban grid at 10 GHz):
342
421
 
343
422
  ```text
344
423
  model cell load rate [Mbit/s] delivered SINR [dB] failures/UE-min
345
- fixed 0.28 14.25 0.98 24.3 0.12
346
- full_buffer 0.52 725.93 0.49 21.9 0.08
347
- periodic 0.28 0.04 0.80 24.4 0.12
348
- ftp3 0.28 3.93 0.85 24.4 0.12
424
+ fixed 0.28 14.10 0.97 23.6 0.08
425
+ full_buffer 0.52 717.77 0.48 21.2 0.08
426
+ periodic 0.28 0.04 0.86 23.7 0.08
427
+ ftp3 0.28 3.93 0.87 23.7 0.08
349
428
  ```
350
429
 
351
- Busier cells interfere more: under full buffer the SINR drops by about 2.5 dB. With one seed each
430
+ Busier cells interfere more: under full buffer the SINR drops by about 2.4 dB. With one seed each
352
431
  failure rate counts only a few failures; compare them over several seeds.
353
432
 
354
433
  The full script is [examples/compare_a3_cho.py](https://github.com/mjs19971997/handoverlab/blob/main/examples/compare_a3_cho.py). Writing your own
@@ -422,19 +501,44 @@ the pages are plain Markdown in [docs/](https://github.com/mjs19971997/handoverl
422
501
  20. 1.11.0: the TR 37.885 highway, the card audit, the bandit against an exhaustive search, the
423
502
  `dqn` rule and the optional Numba kernel.
424
503
  21. 1.12.0: radio maps from ray tracing or measurements.
425
- 22. **2.0.0 (this release)**: a LEO satellite with earth-moving beams and conditional handover with
504
+ 22. 2.0.0: a LEO satellite with earth-moving beams and conditional handover with
426
505
  event D2; the 3GPP values as defaults, with a switch back to 1.x.
427
- 23. Later (planned, not done): the failure model checked on held-out measurements, the sensitivity of
428
- the results to the time step (LTM and beams), a reproducible benchmark package against
429
- ns-3 / 5G-LENA, a table of model boundaries, condEventT1 and earth-fixed beams.
506
+ 23. 2.1.0: the clause-by-clause standard audit; held-out validation of the failure model, the
507
+ time-step study, the ns-3 benchmark package and the table of model boundaries.
508
+ 24. 2.2.0: fast fading with link-to-system mapping; the slot scheduler with MCS, TBS and HARQ.
509
+ 25. 2.3.0: buffers at handover, urban macro, SMa and O2I, the high-speed train, dual connectivity.
510
+ 26. 2.4.0: UE receive beams, the TR 38.744 prediction rule, the compiled
511
+ scheduler, the 7 GHz calibration and the comparison with other simulators.
512
+ 27. 2.4.1: pictures, citation and tutorials brought up to date; the example study
513
+ completes again; no change of results.
514
+ 28. **2.4.2 (this release)**: every option has a picture; the dashboard pictures show the current version;
515
+ guide and tutorial examples rerun; facts made consistent; no change of results.
516
+ 29. Later (planned, not done), staying a handover simulator: the effect of a handover on what the user
517
+ sees (simple TCP and application models on top of the buffers), MIMO as an SINR gain, hundreds of
518
+ users per run, and one scenario definition that also runs in ns-3; condEventT1 and earth-fixed beams.
430
519
 
431
520
  ## Citation
432
521
 
433
522
  If you use HandoverLab, please cite it as described in [CITATION.cff](https://github.com/mjs19971997/handoverlab/blob/main/CITATION.cff) (GitHub shows
434
- it under *Cite this repository*). The releases are archived on Zenodo:
523
+ it under *Cite this repository*). Every release is archived on Zenodo:
435
524
  [doi:10.5281/zenodo.23409131](https://doi.org/10.5281/zenodo.23409131) cites all versions (it resolves to
436
- the latest); version 1.0.0 is [doi:10.5281/zenodo.23409132](https://doi.org/10.5281/zenodo.23409132)
437
- and version 1.0.1 [doi:10.5281/zenodo.23409402](https://doi.org/10.5281/zenodo.23409402).
525
+ the latest). To cite the exact version you used, take its DOI from the version list on that page, where
526
+ the DOI of the latest version is listed; for example, version 2.4.1 is
527
+ [doi:10.5281/zenodo.23585308](https://doi.org/10.5281/zenodo.23585308) and version 2.4.0
528
+ [doi:10.5281/zenodo.23582521](https://doi.org/10.5281/zenodo.23582521). The BibTeX entry below cites 2.4.1;
529
+ replace version and DOI with those of the version you used.
530
+
531
+ ```bibtex
532
+ @software{handoverlab,
533
+ author = {Jalili Sanjarani, Mostafa and Elmi Sola, Yasser},
534
+ title = {{HandoverLab}: system-level handover simulator for 5G-Advanced and beyond-5G research},
535
+ year = {2026},
536
+ publisher = {Zenodo},
537
+ version = {2.4.1},
538
+ doi = {10.5281/zenodo.23585308},
539
+ url = {https://github.com/mjs19971997/handoverlab}
540
+ }
541
+ ```
438
542
 
439
543
  ## Licence
440
544
 
@@ -91,8 +91,9 @@ InterDigital and ZTE, "Calibration Results for 7 - 24 GHz SI";
91
91
  `Calibration_LS_v35`, based on TR 38.901 V19.0.0). The criteria were fixed before the first run: every
92
92
  percentile 5-95 % inside the company range widened by 0.5 dB (C1, the rule of the cases above), and the
93
93
  largest distance from the company mean at most 1.5 dB per case (C2). Result, 30 000 users per case, seed 1:
94
- **C1 passes for all 18 case-metric pairs (342 of 342 percentiles strictly inside the range); C2 fails for all
95
- six cases (largest distance 1.65-2.88 dB).** `handoverlab verify` runs C1 as checks and C2 as notes in the
94
+ **C1 passes for all 18 case-metric pairs of the six cases (342 of 342 percentiles strictly inside the range;
95
+ 228 of 228 for the four 7 GHz cases); C2 fails for all six cases (largest distance 1.65-2.88 dB; 1.69-2.43 dB
96
+ for the four 7 GHz cases, 1.65 and 2.88 dB for the two 6 GHz reruns).** `handoverlab verify` runs C1 as checks and C2 as notes in the
96
97
  group `calibration`.
97
98
 
98
99
  **The reference.** `src/handoverlab/verify/data/r1_2506406.csv` keeps, in the format of `r1_165974.csv`, the