xcoll 0.5.11__py3-none-any.whl → 0.6.0__py3-none-any.whl

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.

Potentially problematic release.


This version of xcoll might be problematic. Click here for more details.

Files changed (333) hide show
  1. xcoll/__init__.py +5 -18
  2. xcoll/beam_elements/__init__.py +1 -0
  3. xcoll/beam_elements/absorber.py +12 -2
  4. xcoll/beam_elements/base.py +162 -62
  5. xcoll/beam_elements/blowup.py +1 -0
  6. xcoll/beam_elements/elements_src/black_absorber.h +57 -58
  7. xcoll/beam_elements/elements_src/black_crystal.h +49 -50
  8. xcoll/beam_elements/elements_src/everest_block.h +21 -11
  9. xcoll/beam_elements/elements_src/everest_collimator.h +100 -91
  10. xcoll/beam_elements/elements_src/everest_crystal.h +145 -140
  11. xcoll/beam_elements/elements_src/transparent_collimator.h +126 -0
  12. xcoll/beam_elements/elements_src/transparent_crystal.h +118 -0
  13. xcoll/beam_elements/everest.py +16 -5
  14. xcoll/beam_elements/monitor.py +1 -0
  15. xcoll/beam_elements/transparent.py +83 -0
  16. xcoll/colldb.py +15 -6
  17. xcoll/general.py +1 -1
  18. xcoll/headers/particle_states.py +51 -0
  19. xcoll/initial_distribution.py +129 -103
  20. xcoll/interaction_record/interaction_record.py +2 -1
  21. xcoll/interaction_record/interaction_types.py +2 -2
  22. xcoll/line_tools.py +163 -74
  23. xcoll/lossmap.py +519 -127
  24. xcoll/plot.py +109 -0
  25. xcoll/rf_sweep.py +6 -0
  26. xcoll/scattering_routines/engine.py +600 -0
  27. xcoll/scattering_routines/environment.py +297 -0
  28. xcoll/scattering_routines/everest/amorphous.h +95 -71
  29. xcoll/scattering_routines/everest/{channeling.h → channelling.h} +121 -112
  30. xcoll/scattering_routines/everest/constants.h +1 -1
  31. xcoll/scattering_routines/everest/crystal_parameters.h +9 -9
  32. xcoll/scattering_routines/everest/everest.h +8 -3
  33. xcoll/scattering_routines/everest/everest.py +2 -1
  34. xcoll/scattering_routines/everest/ionisation_loss.h +141 -0
  35. xcoll/scattering_routines/everest/jaw.h +19 -24
  36. xcoll/scattering_routines/everest/materials.py +2 -0
  37. xcoll/scattering_routines/everest/multiple_coulomb_scattering.h +2 -2
  38. xcoll/scattering_routines/everest/nuclear_interaction.h +35 -19
  39. xcoll/scattering_routines/everest/properties.h +4 -73
  40. xcoll/xaux.py +73 -0
  41. {xcoll-0.5.11.dist-info → xcoll-0.6.0.dist-info}/METADATA +5 -5
  42. xcoll-0.6.0.dist-info/RECORD +135 -0
  43. xcoll/_manager.py +0 -22
  44. xcoll/headers/particle_states.h +0 -25
  45. xcoll/install.py +0 -35
  46. xcoll/scattering_routines/geant4/collimasim/.git +0 -1
  47. xcoll/scattering_routines/geant4/collimasim/.gitignore +0 -12
  48. xcoll/scattering_routines/geant4/collimasim/.gitmodules +0 -3
  49. xcoll/scattering_routines/geant4/collimasim/CMakeLists.txt +0 -26
  50. xcoll/scattering_routines/geant4/collimasim/README.md +0 -21
  51. xcoll/scattering_routines/geant4/collimasim/docs/Makefile +0 -20
  52. xcoll/scattering_routines/geant4/collimasim/docs/make.bat +0 -35
  53. xcoll/scattering_routines/geant4/collimasim/docs/source/collimasim.rst +0 -10
  54. xcoll/scattering_routines/geant4/collimasim/docs/source/conf.py +0 -59
  55. xcoll/scattering_routines/geant4/collimasim/docs/source/index.rst +0 -26
  56. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.appveyor.yml +0 -37
  57. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.clang-format +0 -19
  58. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.clang-tidy +0 -65
  59. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.cmake-format.yaml +0 -73
  60. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.git +0 -1
  61. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/CODEOWNERS +0 -9
  62. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/CONTRIBUTING.md +0 -386
  63. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/ISSUE_TEMPLATE/bug-report.yml +0 -45
  64. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/ISSUE_TEMPLATE/config.yml +0 -8
  65. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/dependabot.yml +0 -16
  66. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/labeler.yml +0 -8
  67. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/labeler_merged.yml +0 -3
  68. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/pull_request_template.md +0 -19
  69. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/ci.yml +0 -969
  70. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/configure.yml +0 -84
  71. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/format.yml +0 -48
  72. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/labeler.yml +0 -16
  73. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/pip.yml +0 -103
  74. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.gitignore +0 -45
  75. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.pre-commit-config.yaml +0 -151
  76. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.readthedocs.yml +0 -3
  77. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/CMakeLists.txt +0 -297
  78. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/LICENSE +0 -29
  79. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/MANIFEST.in +0 -6
  80. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/README.rst +0 -180
  81. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/Doxyfile +0 -23
  82. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/Makefile +0 -192
  83. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/_static/theme_overrides.css +0 -11
  84. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/chrono.rst +0 -81
  85. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/custom.rst +0 -93
  86. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/eigen.rst +0 -310
  87. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/functional.rst +0 -109
  88. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/index.rst +0 -43
  89. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/overview.rst +0 -171
  90. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/stl.rst +0 -251
  91. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/strings.rst +0 -305
  92. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/classes.rst +0 -1297
  93. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/embedding.rst +0 -262
  94. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/exceptions.rst +0 -396
  95. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/functions.rst +0 -568
  96. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/misc.rst +0 -337
  97. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/pycpp/index.rst +0 -13
  98. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/pycpp/numpy.rst +0 -463
  99. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/pycpp/object.rst +0 -286
  100. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/pycpp/utilities.rst +0 -155
  101. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/smart_ptrs.rst +0 -174
  102. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/basics.rst +0 -308
  103. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/benchmark.py +0 -91
  104. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/benchmark.rst +0 -95
  105. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/changelog.rst +0 -2050
  106. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/classes.rst +0 -542
  107. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/cmake/index.rst +0 -8
  108. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/compiling.rst +0 -648
  109. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/conf.py +0 -381
  110. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/faq.rst +0 -343
  111. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/index.rst +0 -48
  112. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/installing.rst +0 -105
  113. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/limitations.rst +0 -72
  114. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11-logo.png +0 -0
  115. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11_vs_boost_python1.png +0 -0
  116. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11_vs_boost_python1.svg +0 -427
  117. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11_vs_boost_python2.png +0 -0
  118. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11_vs_boost_python2.svg +0 -427
  119. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/reference.rst +0 -130
  120. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/release.rst +0 -96
  121. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/requirements.txt +0 -8
  122. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/upgrade.rst +0 -548
  123. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/attr.h +0 -605
  124. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/buffer_info.h +0 -144
  125. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/cast.h +0 -1432
  126. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/chrono.h +0 -213
  127. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/common.h +0 -2
  128. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/complex.h +0 -65
  129. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/class.h +0 -709
  130. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/common.h +0 -1021
  131. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/descr.h +0 -104
  132. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/init.h +0 -346
  133. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/internals.h +0 -467
  134. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/type_caster_base.h +0 -978
  135. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/typeid.h +0 -55
  136. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/eigen.h +0 -606
  137. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/embed.h +0 -284
  138. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/eval.h +0 -163
  139. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/functional.h +0 -121
  140. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/gil.h +0 -193
  141. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/iostream.h +0 -275
  142. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/numpy.h +0 -1741
  143. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/operators.h +0 -163
  144. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/options.h +0 -65
  145. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/pybind11.h +0 -2497
  146. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/pytypes.h +0 -1879
  147. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/stl/filesystem.h +0 -103
  148. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/stl.h +0 -375
  149. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/stl_bind.h +0 -747
  150. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/noxfile.py +0 -88
  151. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/__init__.py +0 -11
  152. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/__main__.py +0 -52
  153. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/_version.py +0 -12
  154. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/_version.pyi +0 -6
  155. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/commands.py +0 -21
  156. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/py.typed +0 -0
  157. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/setup_helpers.py +0 -482
  158. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/setup_helpers.pyi +0 -63
  159. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pyproject.toml +0 -41
  160. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/setup.cfg +0 -56
  161. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/setup.py +0 -155
  162. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/CMakeLists.txt +0 -503
  163. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/conftest.py +0 -208
  164. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/constructor_stats.h +0 -275
  165. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/cross_module_gil_utils.cpp +0 -73
  166. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/env.py +0 -33
  167. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/extra_python_package/pytest.ini +0 -0
  168. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/extra_python_package/test_files.py +0 -279
  169. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/extra_setuptools/pytest.ini +0 -0
  170. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/extra_setuptools/test_setuphelper.py +0 -143
  171. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/local_bindings.h +0 -85
  172. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/object.h +0 -179
  173. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/pybind11_cross_module_tests.cpp +0 -151
  174. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/pybind11_tests.cpp +0 -91
  175. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/pybind11_tests.h +0 -85
  176. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/pytest.ini +0 -19
  177. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/requirements.txt +0 -12
  178. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_async.cpp +0 -26
  179. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_async.py +0 -25
  180. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_buffers.cpp +0 -216
  181. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_buffers.py +0 -163
  182. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_builtin_casters.cpp +0 -286
  183. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_builtin_casters.py +0 -536
  184. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_call_policies.cpp +0 -107
  185. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_call_policies.py +0 -248
  186. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_callbacks.cpp +0 -227
  187. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_callbacks.py +0 -202
  188. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_chrono.cpp +0 -84
  189. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_chrono.py +0 -210
  190. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_class.cpp +0 -550
  191. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_class.py +0 -473
  192. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/CMakeLists.txt +0 -84
  193. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/embed.cpp +0 -21
  194. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/installed_embed/CMakeLists.txt +0 -28
  195. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/installed_function/CMakeLists.txt +0 -39
  196. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/installed_target/CMakeLists.txt +0 -46
  197. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/main.cpp +0 -6
  198. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt +0 -41
  199. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/subdirectory_function/CMakeLists.txt +0 -35
  200. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/subdirectory_target/CMakeLists.txt +0 -41
  201. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/test.py +0 -10
  202. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_constants_and_functions.cpp +0 -165
  203. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_constants_and_functions.py +0 -53
  204. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_copy_move.cpp +0 -238
  205. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_copy_move.py +0 -126
  206. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_custom_type_casters.cpp +0 -141
  207. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_custom_type_casters.py +0 -117
  208. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_custom_type_setup.cpp +0 -41
  209. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_custom_type_setup.py +0 -50
  210. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_docstring_options.cpp +0 -69
  211. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_docstring_options.py +0 -42
  212. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eigen.cpp +0 -348
  213. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eigen.py +0 -771
  214. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/CMakeLists.txt +0 -47
  215. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/catch.cpp +0 -22
  216. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/external_module.cpp +0 -23
  217. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/test_interpreter.cpp +0 -326
  218. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/test_interpreter.py +0 -15
  219. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_enum.cpp +0 -148
  220. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_enum.py +0 -272
  221. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eval.cpp +0 -119
  222. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eval.py +0 -51
  223. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eval_call.py +0 -5
  224. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_exceptions.cpp +0 -285
  225. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_exceptions.h +0 -12
  226. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_exceptions.py +0 -265
  227. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_factory_constructors.cpp +0 -397
  228. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_factory_constructors.py +0 -520
  229. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_gil_scoped.cpp +0 -49
  230. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_gil_scoped.py +0 -94
  231. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_iostream.cpp +0 -125
  232. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_iostream.py +0 -331
  233. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_kwargs_and_defaults.cpp +0 -153
  234. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_kwargs_and_defaults.py +0 -284
  235. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_local_bindings.cpp +0 -107
  236. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_local_bindings.py +0 -257
  237. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_methods_and_attributes.cpp +0 -412
  238. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_methods_and_attributes.py +0 -517
  239. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_modules.cpp +0 -102
  240. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_modules.py +0 -92
  241. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_multiple_inheritance.cpp +0 -233
  242. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_multiple_inheritance.py +0 -360
  243. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_array.cpp +0 -472
  244. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_array.py +0 -593
  245. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_dtypes.cpp +0 -524
  246. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_dtypes.py +0 -441
  247. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_vectorize.cpp +0 -103
  248. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_vectorize.py +0 -267
  249. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_opaque_types.cpp +0 -73
  250. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_opaque_types.py +0 -59
  251. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_operator_overloading.cpp +0 -235
  252. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_operator_overloading.py +0 -146
  253. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_pickling.cpp +0 -189
  254. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_pickling.py +0 -82
  255. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_pytypes.cpp +0 -560
  256. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_pytypes.py +0 -651
  257. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_sequences_and_iterators.cpp +0 -500
  258. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_sequences_and_iterators.py +0 -253
  259. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_smart_ptr.cpp +0 -452
  260. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_smart_ptr.py +0 -318
  261. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_stl.cpp +0 -342
  262. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_stl.py +0 -291
  263. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_stl_binders.cpp +0 -131
  264. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_stl_binders.py +0 -318
  265. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_tagbased_polymorphic.cpp +0 -144
  266. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_tagbased_polymorphic.py +0 -29
  267. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_thread.cpp +0 -66
  268. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_thread.py +0 -44
  269. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_union.cpp +0 -22
  270. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_union.py +0 -9
  271. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_virtual_functions.cpp +0 -510
  272. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_virtual_functions.py +0 -408
  273. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/valgrind-numpy-scipy.supp +0 -140
  274. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/valgrind-python.supp +0 -117
  275. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/FindCatch.cmake +0 -70
  276. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/FindEigen3.cmake +0 -86
  277. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/FindPythonLibsNew.cmake +0 -257
  278. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/check-style.sh +0 -44
  279. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/cmake_uninstall.cmake.in +0 -23
  280. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/libsize.py +0 -39
  281. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/make_changelog.py +0 -64
  282. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pybind11Common.cmake +0 -402
  283. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pybind11Config.cmake.in +0 -233
  284. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pybind11NewTools.cmake +0 -276
  285. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pybind11Tools.cmake +0 -214
  286. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pyproject.toml +0 -3
  287. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/setup_global.py.in +0 -65
  288. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/setup_main.py.in +0 -41
  289. xcoll/scattering_routines/geant4/collimasim/pyproject.toml +0 -8
  290. xcoll/scattering_routines/geant4/collimasim/setup.py +0 -144
  291. xcoll/scattering_routines/geant4/collimasim/src/collimasim/BDSPyATInterface.cpp +0 -403
  292. xcoll/scattering_routines/geant4/collimasim/src/collimasim/BDSPyATInterface.hh +0 -100
  293. xcoll/scattering_routines/geant4/collimasim/src/collimasim/BDSXtrackInterface.cpp +0 -763
  294. xcoll/scattering_routines/geant4/collimasim/src/collimasim/BDSXtrackInterface.hh +0 -118
  295. xcoll/scattering_routines/geant4/collimasim/src/collimasim/__init__.py +0 -8
  296. xcoll/scattering_routines/geant4/collimasim/src/collimasim/bindings.cpp +0 -63
  297. xcoll/scattering_routines/geant4/collimasim/src/collimasim/pyCollimatorPass.py +0 -142
  298. xcoll/scattering_routines/geant4/collimasim/src/collimasim/xtrack_collimator.py +0 -556
  299. xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/PKG-INFO +0 -6
  300. xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/SOURCES.txt +0 -24
  301. xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/dependency_links.txt +0 -1
  302. xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/not-zip-safe +0 -1
  303. xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/top_level.txt +0 -1
  304. xcoll/scattering_routines/geant4/collimasim/tests/README.md +0 -25
  305. xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_forions.dat +0 -25
  306. xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_new_example.dat +0 -18
  307. xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_old_example.dat +0 -68
  308. xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_testing.dat +0 -15
  309. xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_yaml_example.yaml +0 -110
  310. xcoll/scattering_routines/geant4/collimasim/tests/resources/collgaps.dat +0 -7
  311. xcoll/scattering_routines/geant4/collimasim/tests/resources/collgaps_pyat_test.dat +0 -3
  312. xcoll/scattering_routines/geant4/collimasim/tests/resources/collonly_twiss_file_example.tfs +0 -54
  313. xcoll/scattering_routines/geant4/collimasim/tests/resources/settings.gmad +0 -3
  314. xcoll/scattering_routines/geant4/collimasim/tests/resources/settings_black_absorber.gmad +0 -3
  315. xcoll/scattering_routines/geant4/collimasim/tests/resources/settings_ions.gmad +0 -5
  316. xcoll/scattering_routines/geant4/collimasim/tests/resources/twiss_file_testing.tfs +0 -51
  317. xcoll/scattering_routines/geant4/collimasim/tests/test_pyat.py +0 -65
  318. xcoll/scattering_routines/geant4/collimasim/tests/test_pyat_passmethod.py +0 -59
  319. xcoll/scattering_routines/geant4/collimasim/tests/test_pyat_tracking.py +0 -102
  320. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack.py +0 -75
  321. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_angle.py +0 -74
  322. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_colldb_load.py +0 -84
  323. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_interaction.py +0 -159
  324. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_interaction_ion.py +0 -99
  325. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_ions.py +0 -78
  326. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_lost_energy.py +0 -88
  327. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_tilt.py +0 -80
  328. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_tracking.py +0 -97
  329. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_tracking_ions.py +0 -96
  330. xcoll-0.5.11.dist-info/RECORD +0 -413
  331. {xcoll-0.5.11.dist-info → xcoll-0.6.0.dist-info}/LICENSE +0 -0
  332. {xcoll-0.5.11.dist-info → xcoll-0.6.0.dist-info}/NOTICE +0 -0
  333. {xcoll-0.5.11.dist-info → xcoll-0.6.0.dist-info}/WHEEL +0 -0
xcoll/lossmap.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # copyright ############################### #
2
2
  # This file is part of the Xcoll package. #
3
- # Copyright (c) CERN, 2024. #
3
+ # Copyright (c) CERN, 2025. #
4
4
  # ######################################### #
5
5
 
6
6
  import numpy as np
@@ -9,86 +9,114 @@ from pathlib import Path
9
9
  import json
10
10
 
11
11
  import xtrack as xt
12
- import xpart as xp
13
12
  import xobjects as xo
14
13
 
15
14
  from .beam_elements import collimator_classes, crystal_classes
15
+ from .general import __version__
16
+ from .plot import _plot_lossmap_base
17
+ from .headers.particle_states import (
18
+ LOST_ON_EVEREST_BLOCK, LOST_ON_EVEREST_COLL, LOST_ON_EVEREST_CRYSTAL,
19
+ LOST_ON_FLUKA_BLOCK, LOST_ON_FLUKA_COLL, LOST_ON_FLUKA_CRYSTAL,
20
+ LOST_ON_GEANT4_BLOCK, LOST_ON_GEANT4_COLL, LOST_ON_GEANT4_CRYSTAL,
21
+ LOST_ON_ABSORBER, MASSLESS_OR_NEUTRAL, ACC_IONISATION_LOSS,
22
+ VIRTUAL_ENERGY)
16
23
 
17
24
 
18
25
  class LossMap:
19
-
20
- def __init__(self, line, part, *, line_is_reversed, interpolation=0.1,
21
- weights=None, weight_function=None, verbose=True):
22
- self._line = line
26
+ def __init__(self, line, part, *, line_is_reversed, interpolation=None,
27
+ line_shift_s=0, weights=None, weight_function=None, verbose=True):
23
28
  self._line_is_reversed = line_is_reversed
24
- self._machine_length = line.get_length()
25
- self._part = part
29
+ self._machine_length = line.get_length() if line else None
26
30
  self._interpolation = interpolation
27
- if weights is None:
28
- if weight_function is None:
29
- self._weights = np.ones(len(part.x))
30
- else:
31
- self._weights = _create_weights_from_initial_state(part, weight_function)
32
- else:
33
- if weight_function is not None:
34
- raise ValueError("Use either 'weights' or 'weight_function', not both!")
35
- self._weights = part.sort(interleave_lost_particles=True)
36
-
37
- # Correct particles that are lost in aperture directly after collimator -> should be absorbed
38
- self._correct_absorbed(verbose=verbose)
39
-
40
- # Loss location refinement
41
- if interpolation is not None:
42
- self._interpolate()
43
-
44
- self._make_coll_summary()
45
- coll_summary = self._summary[self._summary.nabs > 0].to_dict('list')
46
- aper_s, aper_names, aper_nabs, aper_energy = self._get_aperture_losses()
47
-
48
- self._lossmap = {
49
- 'collimator': {
50
- 's': coll_summary['s'],
51
- 'name': coll_summary['collname'],
52
- 'length': coll_summary['length'],
53
- 'n': coll_summary['nabs'],
54
- # 'e': coll_summary['energy']
55
- }
56
- ,
57
- 'aperture': {
58
- 's': aper_s,
59
- 'name': aper_names,
60
- 'n': aper_nabs,
61
- # 'e': aper_energy
62
- }
63
- ,
64
- 'machine_length': self._machine_length
65
- ,
66
- 'interpolation': interpolation
67
- ,
68
- 'reversed': self._line_is_reversed
69
- }
70
-
31
+ self._momentum = line.particle_ref.p0c[0] if line else None
32
+ self._aper_s = np.array([])
33
+ self._aper_nabs = np.array([])
34
+ self._aper_eabs = np.array([])
35
+ self._aperbins = np.array([])
36
+ self._aperbins_length = np.array([])
37
+ self._aperbinned = np.array([])
38
+ self._aperbinned_energy = np.array([])
39
+ self._coll_s = np.array([])
40
+ self._coll_name = np.array([])
41
+ self._coll_nabs = np.array([])
42
+ self._coll_eabs = np.array([])
43
+ self._coll_length = np.array([])
44
+ self._coll_type = np.array([])
45
+ self._xcoll = __version__
46
+ self._energy_waring_given = False
47
+ if part and line:
48
+ self.add_particles(part=part, line=line, line_shift_s=line_shift_s,
49
+ weights=weights, weight_function=weight_function,
50
+ verbose=verbose)
51
+
52
+ def __str__(self):
53
+ return f"LossMap ({self.num_aperture_losses} losses on aperture and " \
54
+ + f"{self.num_collimator_losses} losses on collimators)"
55
+
56
+ def __repr__(self):
57
+ return f"<{str(self)} at {hex(id(self))}>"
58
+
59
+ @classmethod
60
+ def from_json(cls, file, verbose=True):
61
+ lm = cls(None, None, line_is_reversed=None)
62
+ lm.add_from_json(file, verbose=verbose)
63
+ return lm
71
64
 
72
65
  def to_json(self, file):
73
66
  with open(Path(file), 'w') as fid:
74
- json.dump(self._lossmap, fid, indent=True, cls=xo.JEncoder)
67
+ json.dump({
68
+ 'xcoll': self._xcoll,
69
+ 'date': pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S'),
70
+ **self.lossmap
71
+ }, fid, indent=True, cls=xo.JEncoder)
75
72
 
76
73
  def save_summary(self, file):
77
74
  with open(Path(file), 'w') as fid:
78
- fid.write(self._summary.__repr__())
75
+ fid.write(self.summary.__repr__())
79
76
 
80
77
 
81
78
  @property
82
79
  def lossmap(self):
83
- return self._lossmap
80
+ coll_summary = self.summary[self.summary.n > 0].to_dict('list')
81
+ coll_summary = {kk: np.array(vv) for kk, vv in coll_summary.items()}
82
+ return {
83
+ 'collimator': coll_summary,
84
+ 'aperture': self.aperture_losses,
85
+ 'machine_length': self.machine_length,
86
+ 'interpolation': self.interpolation,
87
+ 'reversed': self.line_is_reversed,
88
+ 'momentum': self._momentum,
89
+ }
84
90
 
85
91
  @property
86
92
  def summary(self):
87
- return self._summary
93
+ return pd.DataFrame({
94
+ 'name': self._coll_name,
95
+ 'n': self._coll_nabs,
96
+ 'e': self._coll_eabs,
97
+ 'length': self._coll_length,
98
+ 's': self._coll_s,
99
+ 'type': self._coll_type,
100
+ }).sort_values("s")
88
101
 
89
102
  @property
90
- def line(self):
91
- return self._line
103
+ def aperture_losses(self):
104
+ if self._interpolation:
105
+ mask = self._aperbinned > 0
106
+ aper_s = self._aperbins[:-1] + self.interpolation/2
107
+ return {
108
+ 'idx_bins': np.arange(len(self._aperbins)-1)[mask],
109
+ 's_bins': aper_s[mask],
110
+ 'n_bins': self._aperbinned[mask],
111
+ 'e_bins': self._aperbinned_energy[mask],
112
+ 'length_bins': self._aperbins_length[mask],
113
+ }
114
+ else:
115
+ return {
116
+ 's': self._aper_s,
117
+ 'n': self._aper_nabs,
118
+ 'e': self._aper_eabs
119
+ }
92
120
 
93
121
  @property
94
122
  def line_is_reversed(self):
@@ -98,112 +126,476 @@ class LossMap:
98
126
  def machine_length(self):
99
127
  return self._machine_length
100
128
 
101
- @property
102
- def part(self):
103
- return self._part
104
-
105
129
  @property
106
130
  def interpolation(self):
107
131
  return self._interpolation
108
132
 
109
133
  @property
110
- def weights(self):
111
- return self._weights
134
+ def momentum(self):
135
+ return self._momentum
136
+
137
+ @property
138
+ def num_losses(self):
139
+ return self.num_aperture_losses + self.num_collimator_losses
140
+
141
+ @property
142
+ def num_aperture_losses(self):
143
+ return int(self._aperbinned.sum() + self._aper_nabs.sum())
144
+
145
+ @property
146
+ def num_collimator_losses(self):
147
+ return int(self._coll_nabs.sum())
148
+
149
+
150
+ def plot(self, *, norm="total", ax=None, xlim=None, ylim=None, legend=True,
151
+ grid=True, energy=False, show=True, savefig=None):
152
+ return _plot_lossmap_base(self.lossmap, norm=norm, ax=ax, xlim=xlim,
153
+ ylim=ylim, legend=legend, grid=grid, energy=energy,
154
+ show=show, savefig=savefig)
155
+
156
+ def add_particles(self, part, line, *, line_shift_s=0, weights=None,
157
+ weight_function=None, verbose=True):
158
+ """
159
+ Add particles to the loss map. Aperture losses are interpolated and the
160
+ collimator summary is updated.
161
+ """
162
+ if self.interpolation is None:
163
+ self._interpolation = 0.1
164
+ if self._machine_length:
165
+ if not np.isclose(self._machine_length, line.get_length()):
166
+ raise ValueError("The line length is different from the one used "
167
+ "to create the loss map.")
168
+ else:
169
+ self._machine_length = line.get_length()
170
+ if self._momentum:
171
+ if not np.isclose(self._momentum, line.particle_ref.p0c[0]):
172
+ raise ValueError("The reference momentum is different from the one "
173
+ "used to create the loss map.")
174
+ else:
175
+ self._momentum = line.particle_ref.p0c[0]
176
+ if weights is None:
177
+ if weight_function is None:
178
+ weights = np.ones(len(part.x))
179
+ else:
180
+ weights = _create_weights_from_initial_state(part, weight_function)
181
+ else:
182
+ if weight_function is not None:
183
+ raise ValueError("Use either 'weights' or 'weight_function', not both!")
184
+ if len(weights) != len(part.x):
185
+ raise ValueError("The length of the weights array must be equal to "
186
+ "the number of particles.")
112
187
 
188
+ if line_shift_s != 0:
189
+ raise NotImplementedError("Line shift not implemented yet.")
113
190
 
114
- def _correct_absorbed(self, verbose=True):
191
+ # Correct particles that are lost in aperture directly after collimator.
192
+ # These should be absorbed.
193
+ self._correct_absorbed(part, line, verbose=verbose)
194
+
195
+ # Loss location refinement
196
+ if self._interpolation:
197
+ self._interpolate(part, line, verbose=verbose)
198
+
199
+ self._make_coll_summary(part, line, line_shift_s, weights)
200
+ self._get_aperture_losses(part, line_shift_s, weights)
201
+
202
+
203
+ def add_from_json(self, file, verbose=True):
204
+ """
205
+ Add loss map data from a JSON file or an iterable of files. The loss map
206
+ is updated with the data from the file(s).
207
+ """
208
+ if hasattr(file, '__iter__') and not isinstance(file, (str, bytes, Path)):
209
+ i = 0
210
+ for ff in file:
211
+ self.add_from_json(ff)
212
+ i += 1
213
+ if verbose:
214
+ print(f"Loaded {i} files into loss map.")
215
+ return
216
+ with open(Path(file), 'r') as fid:
217
+ lossmap = json.load(fid)
218
+ new_style_json = LossMap._assert_valid_json(lossmap)
219
+ if new_style_json:
220
+ if self._momentum is None:
221
+ self._momentum = lossmap['momentum']
222
+ elif not np.isclose(self._momentum, lossmap['momentum']):
223
+ raise ValueError("The momentum is different from the one used "
224
+ "to create the loss map.")
225
+ if self._xcoll != lossmap['xcoll'] and verbose:
226
+ print("Warning: The xcoll version is different from the one used "
227
+ "to create the loss map.")
228
+ if self.line_is_reversed is None:
229
+ self._line_is_reversed = lossmap['reversed']
230
+ elif self.line_is_reversed != lossmap['reversed']:
231
+ raise ValueError("The line_is_reversed is different from the one used "
232
+ "to create the loss map.")
233
+ if self.machine_length is None:
234
+ self._machine_length = lossmap['machine_length']
235
+ elif not np.isclose(self.machine_length, lossmap['machine_length']):
236
+ raise ValueError("The line length is different from the one used "
237
+ "to create the loss map.")
238
+ if self.interpolation is None:
239
+ self._interpolation = lossmap['interpolation']
240
+ elif not np.isclose(self.interpolation, lossmap['interpolation']):
241
+ raise ValueError("The interpolation step is different from the one used "
242
+ "to create the loss map.")
243
+ self._load_coll_summary(lossmap['collimator'])
244
+ self._load_aperture_losses(lossmap['aperture'])
245
+
246
+
247
+ def _correct_absorbed(self, part, line, verbose=True):
115
248
  # Correct particles that are at an aperture directly after a collimator
116
- part = self._part
117
249
  coll_classes = list(set(collimator_classes) - set(crystal_classes))
118
- coll_elements = self._line.get_elements_of_type(coll_classes)[1]
250
+ coll_elements = line.get_elements_of_type(coll_classes)[1]
119
251
  for idx, elem in enumerate(part.at_element):
120
252
  if part.state[idx] == 0:
121
253
  if elem == 0:
122
- prev_elem = len(self._line.element_names) - 1
254
+ prev_elem = len(line.element_names) - 1
123
255
  else:
124
256
  prev_elem = elem - 1
125
- if self._line.element_names[prev_elem] in coll_elements:
257
+ if line.element_names[prev_elem] in coll_elements:
126
258
  if verbose:
127
- print(f"Found at {self._line.element_names[elem]}, "
128
- + f"moved to {self._line.element_names[elem-1]}")
259
+ print(f"Found at {line.element_names[elem]}, "
260
+ + f"moved to {line.element_names[elem-1]}")
129
261
  part.at_element[idx] = elem - 1
130
- what_type = self._line[elem-1].__class__.__name__
131
- if what_type == 'EverestCollimator':
132
- part.state[idx] = -331
262
+ what_type = line[elem-1].__class__.__name__
263
+ if what_type == 'EverestBlock':
264
+ part.state[idx] = LOST_ON_EVEREST_BLOCK
265
+ elif what_type == 'EverestCollimator':
266
+ part.state[idx] = LOST_ON_EVEREST_COLL
133
267
  elif what_type == 'EverestCrystal':
134
- part.state[idx] = -332
268
+ part.state[idx] = LOST_ON_EVEREST_CRYSTAL
269
+ elif what_type == 'FlukaBlock':
270
+ part.state[idx] = LOST_ON_FLUKA_BLOCK
135
271
  elif what_type == 'FlukaCollimator':
136
- part.state[idx] = -334 # TODO: what if crystal?
272
+ part.state[idx] = LOST_ON_FLUKA_COLL
273
+ elif what_type == 'FlukaCrystal':
274
+ part.state[idx] = LOST_ON_FLUKA_CRYSTAL
275
+ elif what_type == 'Geant4Block':
276
+ part.state[idx] = LOST_ON_GEANT4_BLOCK
137
277
  elif what_type == 'Geant4Collimator':
138
- part.state[idx] = -337 # TODO: what if crystal?
278
+ part.state[idx] = LOST_ON_GEANT4_COLL
279
+ elif what_type == 'Geant4Crystal':
280
+ part.state[idx] = LOST_ON_GEANT4_CRYSTAL
139
281
  elif what_type == 'BlackAbsorber':
140
- part.state[idx] = -340
282
+ part.state[idx] = LOST_ON_ABSORBER
141
283
  else:
142
284
  raise ValueError(f"Unknown collimator type {what_type}")
143
285
 
144
- def _interpolate(self):
145
- aper_s = list(self._part.s[self._part.state==0])
146
- if len(aper_s) > 0:
147
- print("Performing the aperture losses refinement.")
286
+
287
+ def _interpolate(self, part, line, verbose=True):
288
+ if len(part.s[part.state==0]) > 0:
289
+ if verbose:
290
+ print("Performing the aperture losses refinement.")
148
291
  loss_loc_refinement = xt.LossLocationRefinement(
149
- self._line,
292
+ line,
150
293
  n_theta = 360, # Angular resolution
151
294
  r_max = 0.5, # Maximum transverse aperture [m]
152
295
  dr = 50e-6, # Transverse accuracy [m]
153
296
  ds = self.interpolation # Longitudinal accuracy [m]
154
297
  )
155
- loss_loc_refinement.refine_loss_location(self._part)
156
-
157
-
158
- def _make_coll_summary(self):
159
- collimator_names = self._line.get_elements_of_type(collimator_classes)[1]
160
- coll_mask = (self._part.state <= -330) & (self._part.state >= -340)
161
- coll_losses = np.array([self._line.element_names[i]
162
- for i in self._part.at_element[coll_mask]])
163
- coll_lengths = [self._line[j].length for j in collimator_names]
164
- coll_pos = [(self._line.get_s_position(i) + self._line[i].length/2)
165
- for i in collimator_names]
298
+ loss_loc_refinement.refine_loss_location(part)
299
+
300
+
301
+ def _make_coll_summary(self, part, line, line_shift_s, weights):
302
+ all_lost_states = [LOST_ON_EVEREST_BLOCK, LOST_ON_EVEREST_COLL, LOST_ON_EVEREST_CRYSTAL,
303
+ LOST_ON_FLUKA_BLOCK, LOST_ON_FLUKA_COLL, LOST_ON_FLUKA_CRYSTAL,
304
+ LOST_ON_GEANT4_BLOCK, LOST_ON_GEANT4_COLL, LOST_ON_GEANT4_CRYSTAL,
305
+ LOST_ON_ABSORBER, MASSLESS_OR_NEUTRAL, ACC_IONISATION_LOSS,
306
+ VIRTUAL_ENERGY
307
+ ]
308
+
309
+ names = line.get_elements_of_type(collimator_classes)[1]
310
+ coll_mask = (part.state <= max(all_lost_states)) & (part.state >= min(all_lost_states))
311
+ coll_losses = np.array([line.element_names[i]
312
+ for i in part.at_element[coll_mask]])
313
+ coll_lengths = [line[name].length for name in names]
314
+
315
+ L = self.machine_length
316
+ coll_pos = [(line.get_s_position(name) + cl/2 + line_shift_s)%L
317
+ for name, cl in zip(names, coll_lengths)]
318
+ if self.line_is_reversed:
319
+ coll_pos = L - coll_pos
320
+
321
+ coll_types = [line[name].__class__.__name__
322
+ for name in names]
323
+ coll_weights = weights[coll_mask]
324
+ nabs = [coll_weights[coll_losses == name].sum()
325
+ for name in names]
326
+ energy_weights = coll_weights * part.energy[coll_mask]
327
+ eabs = [energy_weights[coll_losses == name].sum()
328
+ for name in names]
329
+ self._do_collimator_adding(coll_s=coll_pos, coll_name=names, coll_nabs=nabs,
330
+ coll_eabs=eabs, coll_length=coll_lengths,
331
+ coll_type=coll_types)
332
+
333
+ def _load_coll_summary(self, colldata):
334
+ coll_eabs = colldata['e'] if 'e' in colldata else np.zeros(len(colldata['s']))
335
+ if 'type' in colldata:
336
+ coll_types = colldata['type']
337
+ else:
338
+ coll_types = np.full(len(colldata['s']), "Unknown", dtype=object)
339
+ self._do_collimator_adding(coll_s=colldata['s'], coll_name=colldata['name'],
340
+ coll_nabs=colldata['n'], coll_eabs=coll_eabs,
341
+ coll_length=colldata['length'], coll_type=coll_types)
342
+
343
+ def _do_collimator_adding(self, coll_s, coll_name, coll_nabs, coll_eabs,
344
+ coll_length, coll_type):
345
+ # TODO: this can be done smarter, masks instead of loops, though
346
+ # one should keep in mind that indices can be repeated and then
347
+ # masking does not work correctly
348
+ for ss, nn, nabs, eabs, ll, tt in zip(coll_s, coll_name, coll_nabs,
349
+ coll_eabs, coll_length, coll_type):
350
+ idx, = np.where(self._coll_name == nn)
351
+ if len(idx) == 0:
352
+ self._coll_s = np.append(self._coll_s, ss)
353
+ self._coll_name = np.append(self._coll_name, nn)
354
+ self._coll_nabs = np.append(self._coll_nabs, nabs)
355
+ self._coll_eabs = np.append(self._coll_eabs, eabs)
356
+ self._coll_length = np.append(self._coll_length, ll)
357
+ self._coll_type = np.append(self._coll_type, tt)
358
+ else:
359
+ idx = idx[0]
360
+ if not np.isclose(self._coll_length[idx], ll):
361
+ raise ValueError(f"Length of {nn} is different from the one used "
362
+ + "to create the loss map.")
363
+ if self._coll_type[idx] != tt and tt != 'Unknown':
364
+ raise ValueError(f"Type of {nn} is different from the one used to "
365
+ + "create the loss map.")
366
+ if not np.isclose(self._coll_s[idx], ss):
367
+ raise ValueError(f"s position of {nn} is different from the one "
368
+ + "used to create the loss map.")
369
+ self._coll_nabs[idx] += nabs
370
+ self._coll_eabs[idx] += eabs
371
+
372
+
373
+ def _make_aperture_bins(self):
374
+ if self._aperbins.size == 0:
375
+ L = self.machine_length
376
+ end = L - np.mod(L, self.interpolation) + self.interpolation
377
+ self._aperbins = np.linspace(0, end, int(np.ceil(L/self.interpolation)) + 1)
378
+ # TODO: not entirely correct, as not all bins have the same lenght in practice: If
379
+ # an active element like a magnet starts in the middle of the bin, that bin is
380
+ # essentially shorter. Then the first aperture marker after the element represents
381
+ # the particles that would be lost in this element, so there the aperture length is
382
+ # equal to the element length. This is not true if the active element is a collimator
383
+ # (then the losses are moved to the collimator anyway).
384
+ # TODO: need length for non-interpolated case as well?
385
+ self._aperbins_length = np.full(len(self._aperbins) - 1, self.interpolation, dtype=np.float64)
386
+ self._aperbinned = np.zeros(len(self._aperbins) - 1, dtype=np.float64)
387
+ self._aperbinned_energy = np.zeros(len(self._aperbins) - 1, dtype=np.float64)
388
+
389
+ def _get_aperture_losses(self, part, line_shift_s, weights):
390
+ aper_mask = part.state == 0
391
+ if len(part.s[aper_mask]) == 0:
392
+ return
166
393
 
394
+ # Get s position per particle (lost on aperture)
395
+ L = self.machine_length
396
+ aper_s = np.mod(part.s[aper_mask] + line_shift_s, L)
167
397
  if self._line_is_reversed:
168
- coll_pos = [self._machine_length - s for s in coll_pos]
169
-
170
- coll_types = [self._line[i].__class__.__name__ for i in collimator_names]
171
- coll_weights = self._weights[coll_mask]
172
- nabs = [coll_weights[coll_losses == j].sum() for j in collimator_names]
173
-
174
- self._summary = pd.DataFrame({
175
- 'collname': collimator_names,
176
- 'nabs': nabs, # of particles lost on collimators
177
- # 'energy': energy,
178
- 'length': coll_lengths,
179
- 's': coll_pos,
180
- 'type': coll_types
181
- })
398
+ aper_s = L - aper_s
182
399
 
400
+ if self._interpolation:
401
+ # Binned aperture losses
402
+ self._make_aperture_bins()
403
+ self._do_aperture_binning(aper_s=aper_s, aper_nabs=weights[aper_mask],
404
+ aper_eabs=weights[aper_mask] * part.energy[aper_mask])
405
+ else:
406
+ # Aperture losses at exact s positions (because no interpolation performed)
407
+ # TODO: need correct lengths to scale
408
+ aper_pos = np.unique(aper_s)
409
+ aper_weights = weights[aper_mask]
410
+ aper_nabs = [aper_weights[aper_s == j].sum() for j in aper_pos]
411
+ energy_weights = aper_weights * part.energy[aper_mask]
412
+ aper_eabs = [energy_weights[aper_s == s].sum() for s in aper_pos]
413
+ self._do_aperture_adding(aper_s=aper_pos, aper_nabs=aper_nabs,
414
+ aper_eabs=aper_eabs)
415
+
416
+ def _load_aperture_losses(self, aperdata):
417
+ if self._interpolation:
418
+ self._make_aperture_bins()
419
+ if not 'idx_bins' in aperdata and 's' in aperdata and 'n' in aperdata:
420
+ # Old-style JSON file
421
+ aper_eabs = aperdata['e'] if 'e' in aperdata else np.zeros(len(aperdata['s']))
422
+ self._do_aperture_binning(aper_s=aperdata['s'], aper_nabs=aperdata['n'],
423
+ aper_eabs=aper_eabs)
424
+ else:
425
+ self._aperbinned[aperdata['idx_bins']] = aperdata['n_bins']
426
+ self._aperbinned_energy[aperdata['idx_bins']] = aperdata['e_bins']
427
+ else:
428
+ self._do_aperture_adding(aper_s=aperdata['s'], aper_nabs=aperdata['n'],
429
+ aper_eabs=aperdata['e'])
430
+
431
+ def _do_aperture_binning(self, aper_s, aper_nabs, aper_eabs):
432
+ binned = np.digitize(aper_s, bins=self._aperbins, right=False) - 1
433
+ # We cannot directly use binned as an index, as repeated
434
+ # indices would be ignored
435
+ minlength = len(self._aperbins) - 1
436
+ self._aperbinned += np.bincount(binned, weights=aper_nabs,
437
+ minlength=minlength)
438
+ self._aperbinned_energy += np.bincount(binned, weights=aper_eabs,
439
+ minlength=minlength)
440
+
441
+ def _do_aperture_adding(self, aper_s, aper_nabs, aper_eabs):
442
+ # TODO: this can be done smarter, masks instead of loops, though
443
+ # one should keep in mind that indices can be repeated and then
444
+ # masking does not work correctly
445
+ for ss, nabs, eabs in zip(aper_s, aper_nabs, aper_eabs):
446
+ idx, = np.where(self._aper_s == ss)
447
+ if len(idx) == 0:
448
+ self._aper_s = np.append(self._aper_s, ss)
449
+ self._aper_nabs = np.append(self._aper_nabs, nabs)
450
+ self._aper_eabs = np.append(self._aper_eabs, eabs)
451
+ else:
452
+ idx = idx[0]
453
+ self._aper_nabs[idx] += nabs
454
+ self._aper_eabs[idx] += eabs
455
+
456
+
457
+ @staticmethod
458
+ def _assert_valid_json(lossmap):
459
+ is_new_format = 'xcoll' in lossmap
460
+ if 'machine_length' not in lossmap:
461
+ raise ValueError("The JSON file does not contain the machine length data.")
462
+ if 'interpolation' not in lossmap:
463
+ raise ValueError("The JSON file does not contain the interpolation data.")
464
+ if 'reversed' not in lossmap:
465
+ raise ValueError("The JSON file does not contain the reversed data.")
466
+ if is_new_format:
467
+ if 'momentum' not in lossmap:
468
+ raise ValueError("The JSON file does not contain the momentum data.")
469
+ if 'collimator' not in lossmap:
470
+ raise ValueError("The JSON file does not contain the collimator data.")
471
+ if 's' not in lossmap['collimator']:
472
+ raise ValueError("The JSON file does not contain the collimator s data.")
473
+ if 'name' not in lossmap['collimator']:
474
+ raise ValueError("The JSON file does not contain the collimator name data.")
475
+ if 'length' not in lossmap['collimator']:
476
+ raise ValueError("The JSON file does not contain the collimator length data.")
477
+ if 'n' not in lossmap['collimator']:
478
+ raise ValueError("The JSON file does not contain the collimator n data.")
479
+ if is_new_format:
480
+ if 'e' not in lossmap['collimator']:
481
+ raise ValueError("The JSON file does not contain the collimator energy data.")
482
+ if 'type' not in lossmap['collimator']:
483
+ raise ValueError("The JSON file does not contain the collimator type data.")
484
+ if 'aperture' not in lossmap:
485
+ raise ValueError("The JSON file does not contain the aperture data.")
486
+ if is_new_format and lossmap['interpolation'] is not None:
487
+ if 'idx_bins' not in lossmap['aperture']:
488
+ raise ValueError("The JSON file does not contain the aperture idx_bins data.")
489
+ if 'n_bins' not in lossmap['aperture']:
490
+ raise ValueError("The JSON file does not contain the aperture n_bins data.")
491
+ if 'e_bins' not in lossmap['aperture']:
492
+ raise ValueError("The JSON file does not contain the aperture e_bins data.")
493
+ if 'length_bins' not in lossmap['aperture']:
494
+ raise ValueError("The JSON file does not contain the aperture length_bins data.")
495
+ else:
496
+ if 's' not in lossmap['aperture']:
497
+ raise ValueError("The JSON file does not contain the aperture s data.")
498
+ if 'n' not in lossmap['aperture']:
499
+ raise ValueError("The JSON file does not contain the aperture n data.")
500
+ if is_new_format:
501
+ if 'e' not in lossmap['aperture']:
502
+ raise ValueError("The JSON file does not contain the aperture e data.")
503
+ if 'length' not in lossmap['aperture']:
504
+ raise ValueError("The JSON file does not contain the aperture length data.")
505
+ return is_new_format
506
+
507
+
508
+ class MultiLossMap(LossMap):
509
+ def __init__(self, *lms, **named_lms):
510
+ """
511
+ Create a MultiLossMap object from a list of LossMap objects.
512
+ """
513
+ super().__init__(None, None, line_is_reversed=None)
514
+ del self._line_is_reversed
515
+ self._lms = []
516
+ self._lm_names = []
517
+ if len(lms) > 0:
518
+ if len(named_lms) > 0:
519
+ raise ValueError("Specify the LossMaps as args or kwargs, not both.")
520
+ if hasattr(lms[0], '__iter__'):
521
+ if len(lms) > 1:
522
+ raise ValueError("Use args or a list of LossMap objects, not both.")
523
+ if isinstance(lms[0], dict):
524
+ lms = lms[0].values()
525
+ self._lm_names = lms[0].keys()
526
+ else:
527
+ lms = lms[0]
528
+ elif len(named_lms) > 0:
529
+ lms = named_lms.values()
530
+ self._lm_names = named_lms.keys()
531
+ for lm in lms:
532
+ self.add_lossmap(lm)
183
533
 
184
- def _get_aperture_losses(self):
185
- # Get s position per particle (lost on aperture)
186
- aper_mask = self._part.state == 0
187
- aper_s = list(self._part.s[aper_mask])
188
-
189
- if len(aper_s) == 0:
190
- return [], [], [], []
191
- if self._line_is_reversed:
192
- aper_s = [ self._machine_length - s for s in aper_s ]
534
+ @property
535
+ def lms(self):
536
+ if len(self._lm_names) > 0:
537
+ return dict(zip(self._lm_names, self._lms))
538
+ else:
539
+ return self._lms
193
540
 
194
- # Store names of aperture markers
195
- aper_names = [self._line.element_names[i] for i in self._part.at_element[aper_mask]]
196
- name_dict = dict(zip(aper_s, aper_names)) # TODO: not floating-point-safe and slow
541
+ @property
542
+ def line_is_reversed(self):
543
+ raise AttributeError("The line_is_reversed property is not available "
544
+ + "for MultiLossMap objects.")
197
545
 
198
- # Create output arrays
199
- aper_pos = np.unique(aper_s)
200
- aper_weights = self._weights[aper_mask]
201
- aper_nabs = [aper_weights[aper_s == j].sum() for j in aper_pos]
202
- aper_names = [name_dict[ss] for ss in aper_pos]
546
+ @property
547
+ def lossmap(self):
548
+ coll_summary = self.summary[self.summary.n > 0].to_dict('list')
549
+ coll_summary = {kk: np.array(vv) for kk, vv in coll_summary.items()}
550
+ return {
551
+ 'collimator': coll_summary,
552
+ 'aperture': self.aperture_losses,
553
+ 'machine_length': self.machine_length,
554
+ 'interpolation': self.interpolation,
555
+ 'momentum': self._momentum,
556
+ }
203
557
 
204
- aper_energy = 0
205
558
 
206
- return aper_pos, aper_names, aper_nabs, aper_energy
559
+ def add_lossmap(self, lm):
560
+ """
561
+ Add a LossMap object to the MultiLossMap object.
562
+ """
563
+ if not isinstance(lm, LossMap):
564
+ raise ValueError("The input must be a LossMap object.")
565
+ self._lms.append(lm)
566
+ if self._machine_length is None:
567
+ self._machine_length = lm.machine_length
568
+ elif not np.isclose(self._machine_length, lm.machine_length):
569
+ raise ValueError("The machine lengths of the loss maps are not the same.")
570
+ if self._momentum is None:
571
+ self._momentum = lm.momentum
572
+ elif lm.momentum and not np.isclose(self._momentum, lm.momentum):
573
+ raise ValueError("The momenta of the loss maps are not the same.")
574
+ if self._interpolation is None:
575
+ self._interpolation = lm.interpolation
576
+ elif not np.isclose(self._interpolation, lm.interpolation):
577
+ raise ValueError("The interpolations of the loss maps are not the same.")
578
+ self._do_collimator_adding(coll_s=lm._coll_s, coll_name=lm._coll_name,
579
+ coll_nabs=lm._coll_nabs, coll_eabs=lm._coll_eabs,
580
+ coll_length=lm._coll_length, coll_type=lm._coll_type)
581
+ if self.interpolation:
582
+ if len(lm._aperbins) == 0:
583
+ # No aperture in this loss map
584
+ return
585
+ elif len(self._aperbins) == 0:
586
+ self._aperbins = lm._aperbins
587
+ self._aperbins_length = lm._aperbins_length
588
+ self._aperbinned = lm._aperbinned
589
+ self._aperbinned_energy = lm._aperbinned_energy
590
+ else:
591
+ if len(self._aperbins) != len(lm._aperbins) \
592
+ or not np.allclose(self._aperbins, lm._aperbins):
593
+ raise ValueError("The number of bins of the loss maps are not the same.")
594
+ self._aperbinned += lm._aperbinned
595
+ self._aperbinned_energy += lm._aperbinned_energy
596
+ else:
597
+ self._do_aperture_adding(aper_s=lm._aper_s, aper_nabs=lm._aper_nabs,
598
+ aper_eabs=lm._aper_eabs)
207
599
 
208
600
 
209
601
  def _create_weights_from_initial_state(part, function):