xcoll 0.5.12__py3-none-any.whl → 0.6.1__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 (336) hide show
  1. xcoll/__init__.py +5 -18
  2. xcoll/__init__.py.orig +26 -0
  3. xcoll/beam_elements/__init__.py +1 -0
  4. xcoll/beam_elements/absorber.py +12 -2
  5. xcoll/beam_elements/base.py +162 -62
  6. xcoll/beam_elements/blowup.py +1 -0
  7. xcoll/beam_elements/elements_src/black_absorber.h +57 -58
  8. xcoll/beam_elements/elements_src/black_crystal.h +49 -50
  9. xcoll/beam_elements/elements_src/everest_block.h +21 -11
  10. xcoll/beam_elements/elements_src/everest_collimator.h +100 -91
  11. xcoll/beam_elements/elements_src/everest_crystal.h +145 -140
  12. xcoll/beam_elements/elements_src/transparent_collimator.h +126 -0
  13. xcoll/beam_elements/elements_src/transparent_crystal.h +118 -0
  14. xcoll/beam_elements/everest.py +16 -5
  15. xcoll/beam_elements/monitor.py +1 -0
  16. xcoll/beam_elements/transparent.py +83 -0
  17. xcoll/colldb.py +15 -6
  18. xcoll/general.py +1 -1
  19. xcoll/general.py.orig +20 -0
  20. xcoll/headers/particle_states.py +51 -0
  21. xcoll/initial_distribution.py +121 -91
  22. xcoll/initial_distribution.py.orig +256 -0
  23. xcoll/interaction_record/interaction_record.py +2 -1
  24. xcoll/interaction_record/interaction_types.py +2 -2
  25. xcoll/line_tools.py +163 -73
  26. xcoll/lossmap.py +519 -127
  27. xcoll/plot.py +109 -0
  28. xcoll/rf_sweep.py +6 -0
  29. xcoll/scattering_routines/engine.py +414 -217
  30. xcoll/scattering_routines/environment.py +297 -0
  31. xcoll/scattering_routines/everest/amorphous.h +95 -71
  32. xcoll/scattering_routines/everest/{channeling.h → channelling.h} +121 -112
  33. xcoll/scattering_routines/everest/constants.h +1 -1
  34. xcoll/scattering_routines/everest/crystal_parameters.h +9 -9
  35. xcoll/scattering_routines/everest/everest.h +8 -3
  36. xcoll/scattering_routines/everest/everest.py +2 -1
  37. xcoll/scattering_routines/everest/ionisation_loss.h +141 -0
  38. xcoll/scattering_routines/everest/jaw.h +19 -24
  39. xcoll/scattering_routines/everest/materials.py +2 -0
  40. xcoll/scattering_routines/everest/multiple_coulomb_scattering.h +2 -2
  41. xcoll/scattering_routines/everest/nuclear_interaction.h +35 -19
  42. xcoll/scattering_routines/everest/properties.h +3 -72
  43. xcoll/xaux.py +65 -109
  44. {xcoll-0.5.12.dist-info → xcoll-0.6.1.dist-info}/METADATA +5 -5
  45. xcoll-0.6.1.dist-info/RECORD +138 -0
  46. xcoll/_manager.py +0 -22
  47. xcoll/headers/particle_states.h +0 -25
  48. xcoll/install.py +0 -35
  49. xcoll/scattering_routines/geant4/collimasim/.git +0 -1
  50. xcoll/scattering_routines/geant4/collimasim/.gitignore +0 -12
  51. xcoll/scattering_routines/geant4/collimasim/.gitmodules +0 -3
  52. xcoll/scattering_routines/geant4/collimasim/CMakeLists.txt +0 -26
  53. xcoll/scattering_routines/geant4/collimasim/README.md +0 -21
  54. xcoll/scattering_routines/geant4/collimasim/docs/Makefile +0 -20
  55. xcoll/scattering_routines/geant4/collimasim/docs/make.bat +0 -35
  56. xcoll/scattering_routines/geant4/collimasim/docs/source/collimasim.rst +0 -10
  57. xcoll/scattering_routines/geant4/collimasim/docs/source/conf.py +0 -59
  58. xcoll/scattering_routines/geant4/collimasim/docs/source/index.rst +0 -26
  59. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.appveyor.yml +0 -37
  60. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.clang-format +0 -19
  61. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.clang-tidy +0 -65
  62. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.cmake-format.yaml +0 -73
  63. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.git +0 -1
  64. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/CODEOWNERS +0 -9
  65. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/CONTRIBUTING.md +0 -386
  66. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/ISSUE_TEMPLATE/bug-report.yml +0 -45
  67. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/ISSUE_TEMPLATE/config.yml +0 -8
  68. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/dependabot.yml +0 -16
  69. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/labeler.yml +0 -8
  70. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/labeler_merged.yml +0 -3
  71. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/pull_request_template.md +0 -19
  72. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/ci.yml +0 -969
  73. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/configure.yml +0 -84
  74. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/format.yml +0 -48
  75. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/labeler.yml +0 -16
  76. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/pip.yml +0 -103
  77. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.gitignore +0 -45
  78. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.pre-commit-config.yaml +0 -151
  79. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.readthedocs.yml +0 -3
  80. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/CMakeLists.txt +0 -297
  81. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/LICENSE +0 -29
  82. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/MANIFEST.in +0 -6
  83. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/README.rst +0 -180
  84. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/Doxyfile +0 -23
  85. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/Makefile +0 -192
  86. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/_static/theme_overrides.css +0 -11
  87. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/chrono.rst +0 -81
  88. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/custom.rst +0 -93
  89. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/eigen.rst +0 -310
  90. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/functional.rst +0 -109
  91. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/index.rst +0 -43
  92. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/overview.rst +0 -171
  93. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/stl.rst +0 -251
  94. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/strings.rst +0 -305
  95. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/classes.rst +0 -1297
  96. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/embedding.rst +0 -262
  97. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/exceptions.rst +0 -396
  98. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/functions.rst +0 -568
  99. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/misc.rst +0 -337
  100. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/pycpp/index.rst +0 -13
  101. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/pycpp/numpy.rst +0 -463
  102. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/pycpp/object.rst +0 -286
  103. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/pycpp/utilities.rst +0 -155
  104. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/smart_ptrs.rst +0 -174
  105. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/basics.rst +0 -308
  106. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/benchmark.py +0 -91
  107. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/benchmark.rst +0 -95
  108. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/changelog.rst +0 -2050
  109. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/classes.rst +0 -542
  110. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/cmake/index.rst +0 -8
  111. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/compiling.rst +0 -648
  112. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/conf.py +0 -381
  113. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/faq.rst +0 -343
  114. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/index.rst +0 -48
  115. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/installing.rst +0 -105
  116. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/limitations.rst +0 -72
  117. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11-logo.png +0 -0
  118. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11_vs_boost_python1.png +0 -0
  119. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11_vs_boost_python1.svg +0 -427
  120. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11_vs_boost_python2.png +0 -0
  121. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11_vs_boost_python2.svg +0 -427
  122. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/reference.rst +0 -130
  123. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/release.rst +0 -96
  124. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/requirements.txt +0 -8
  125. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/upgrade.rst +0 -548
  126. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/attr.h +0 -605
  127. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/buffer_info.h +0 -144
  128. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/cast.h +0 -1432
  129. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/chrono.h +0 -213
  130. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/common.h +0 -2
  131. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/complex.h +0 -65
  132. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/class.h +0 -709
  133. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/common.h +0 -1021
  134. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/descr.h +0 -104
  135. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/init.h +0 -346
  136. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/internals.h +0 -467
  137. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/type_caster_base.h +0 -978
  138. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/typeid.h +0 -55
  139. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/eigen.h +0 -606
  140. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/embed.h +0 -284
  141. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/eval.h +0 -163
  142. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/functional.h +0 -121
  143. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/gil.h +0 -193
  144. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/iostream.h +0 -275
  145. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/numpy.h +0 -1741
  146. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/operators.h +0 -163
  147. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/options.h +0 -65
  148. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/pybind11.h +0 -2497
  149. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/pytypes.h +0 -1879
  150. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/stl/filesystem.h +0 -103
  151. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/stl.h +0 -375
  152. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/stl_bind.h +0 -747
  153. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/noxfile.py +0 -88
  154. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/__init__.py +0 -11
  155. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/__main__.py +0 -52
  156. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/_version.py +0 -12
  157. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/_version.pyi +0 -6
  158. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/commands.py +0 -21
  159. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/py.typed +0 -0
  160. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/setup_helpers.py +0 -482
  161. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/setup_helpers.pyi +0 -63
  162. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pyproject.toml +0 -41
  163. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/setup.cfg +0 -56
  164. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/setup.py +0 -155
  165. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/CMakeLists.txt +0 -503
  166. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/conftest.py +0 -208
  167. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/constructor_stats.h +0 -275
  168. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/cross_module_gil_utils.cpp +0 -73
  169. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/env.py +0 -33
  170. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/extra_python_package/pytest.ini +0 -0
  171. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/extra_python_package/test_files.py +0 -279
  172. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/extra_setuptools/pytest.ini +0 -0
  173. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/extra_setuptools/test_setuphelper.py +0 -143
  174. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/local_bindings.h +0 -85
  175. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/object.h +0 -179
  176. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/pybind11_cross_module_tests.cpp +0 -151
  177. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/pybind11_tests.cpp +0 -91
  178. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/pybind11_tests.h +0 -85
  179. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/pytest.ini +0 -19
  180. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/requirements.txt +0 -12
  181. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_async.cpp +0 -26
  182. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_async.py +0 -25
  183. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_buffers.cpp +0 -216
  184. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_buffers.py +0 -163
  185. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_builtin_casters.cpp +0 -286
  186. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_builtin_casters.py +0 -536
  187. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_call_policies.cpp +0 -107
  188. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_call_policies.py +0 -248
  189. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_callbacks.cpp +0 -227
  190. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_callbacks.py +0 -202
  191. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_chrono.cpp +0 -84
  192. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_chrono.py +0 -210
  193. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_class.cpp +0 -550
  194. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_class.py +0 -473
  195. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/CMakeLists.txt +0 -84
  196. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/embed.cpp +0 -21
  197. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/installed_embed/CMakeLists.txt +0 -28
  198. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/installed_function/CMakeLists.txt +0 -39
  199. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/installed_target/CMakeLists.txt +0 -46
  200. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/main.cpp +0 -6
  201. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt +0 -41
  202. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/subdirectory_function/CMakeLists.txt +0 -35
  203. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/subdirectory_target/CMakeLists.txt +0 -41
  204. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/test.py +0 -10
  205. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_constants_and_functions.cpp +0 -165
  206. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_constants_and_functions.py +0 -53
  207. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_copy_move.cpp +0 -238
  208. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_copy_move.py +0 -126
  209. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_custom_type_casters.cpp +0 -141
  210. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_custom_type_casters.py +0 -117
  211. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_custom_type_setup.cpp +0 -41
  212. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_custom_type_setup.py +0 -50
  213. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_docstring_options.cpp +0 -69
  214. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_docstring_options.py +0 -42
  215. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eigen.cpp +0 -348
  216. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eigen.py +0 -771
  217. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/CMakeLists.txt +0 -47
  218. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/catch.cpp +0 -22
  219. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/external_module.cpp +0 -23
  220. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/test_interpreter.cpp +0 -326
  221. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/test_interpreter.py +0 -15
  222. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_enum.cpp +0 -148
  223. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_enum.py +0 -272
  224. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eval.cpp +0 -119
  225. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eval.py +0 -51
  226. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eval_call.py +0 -5
  227. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_exceptions.cpp +0 -285
  228. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_exceptions.h +0 -12
  229. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_exceptions.py +0 -265
  230. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_factory_constructors.cpp +0 -397
  231. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_factory_constructors.py +0 -520
  232. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_gil_scoped.cpp +0 -49
  233. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_gil_scoped.py +0 -94
  234. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_iostream.cpp +0 -125
  235. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_iostream.py +0 -331
  236. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_kwargs_and_defaults.cpp +0 -153
  237. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_kwargs_and_defaults.py +0 -284
  238. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_local_bindings.cpp +0 -107
  239. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_local_bindings.py +0 -257
  240. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_methods_and_attributes.cpp +0 -412
  241. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_methods_and_attributes.py +0 -517
  242. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_modules.cpp +0 -102
  243. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_modules.py +0 -92
  244. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_multiple_inheritance.cpp +0 -233
  245. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_multiple_inheritance.py +0 -360
  246. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_array.cpp +0 -472
  247. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_array.py +0 -593
  248. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_dtypes.cpp +0 -524
  249. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_dtypes.py +0 -441
  250. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_vectorize.cpp +0 -103
  251. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_vectorize.py +0 -267
  252. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_opaque_types.cpp +0 -73
  253. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_opaque_types.py +0 -59
  254. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_operator_overloading.cpp +0 -235
  255. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_operator_overloading.py +0 -146
  256. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_pickling.cpp +0 -189
  257. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_pickling.py +0 -82
  258. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_pytypes.cpp +0 -560
  259. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_pytypes.py +0 -651
  260. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_sequences_and_iterators.cpp +0 -500
  261. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_sequences_and_iterators.py +0 -253
  262. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_smart_ptr.cpp +0 -452
  263. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_smart_ptr.py +0 -318
  264. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_stl.cpp +0 -342
  265. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_stl.py +0 -291
  266. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_stl_binders.cpp +0 -131
  267. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_stl_binders.py +0 -318
  268. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_tagbased_polymorphic.cpp +0 -144
  269. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_tagbased_polymorphic.py +0 -29
  270. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_thread.cpp +0 -66
  271. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_thread.py +0 -44
  272. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_union.cpp +0 -22
  273. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_union.py +0 -9
  274. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_virtual_functions.cpp +0 -510
  275. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_virtual_functions.py +0 -408
  276. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/valgrind-numpy-scipy.supp +0 -140
  277. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/valgrind-python.supp +0 -117
  278. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/FindCatch.cmake +0 -70
  279. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/FindEigen3.cmake +0 -86
  280. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/FindPythonLibsNew.cmake +0 -257
  281. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/check-style.sh +0 -44
  282. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/cmake_uninstall.cmake.in +0 -23
  283. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/libsize.py +0 -39
  284. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/make_changelog.py +0 -64
  285. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pybind11Common.cmake +0 -402
  286. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pybind11Config.cmake.in +0 -233
  287. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pybind11NewTools.cmake +0 -276
  288. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pybind11Tools.cmake +0 -214
  289. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pyproject.toml +0 -3
  290. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/setup_global.py.in +0 -65
  291. xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/setup_main.py.in +0 -41
  292. xcoll/scattering_routines/geant4/collimasim/pyproject.toml +0 -8
  293. xcoll/scattering_routines/geant4/collimasim/setup.py +0 -144
  294. xcoll/scattering_routines/geant4/collimasim/src/collimasim/BDSPyATInterface.cpp +0 -403
  295. xcoll/scattering_routines/geant4/collimasim/src/collimasim/BDSPyATInterface.hh +0 -100
  296. xcoll/scattering_routines/geant4/collimasim/src/collimasim/BDSXtrackInterface.cpp +0 -763
  297. xcoll/scattering_routines/geant4/collimasim/src/collimasim/BDSXtrackInterface.hh +0 -118
  298. xcoll/scattering_routines/geant4/collimasim/src/collimasim/__init__.py +0 -8
  299. xcoll/scattering_routines/geant4/collimasim/src/collimasim/bindings.cpp +0 -63
  300. xcoll/scattering_routines/geant4/collimasim/src/collimasim/pyCollimatorPass.py +0 -142
  301. xcoll/scattering_routines/geant4/collimasim/src/collimasim/xtrack_collimator.py +0 -556
  302. xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/PKG-INFO +0 -6
  303. xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/SOURCES.txt +0 -24
  304. xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/dependency_links.txt +0 -1
  305. xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/not-zip-safe +0 -1
  306. xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/top_level.txt +0 -1
  307. xcoll/scattering_routines/geant4/collimasim/tests/README.md +0 -25
  308. xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_forions.dat +0 -25
  309. xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_new_example.dat +0 -18
  310. xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_old_example.dat +0 -68
  311. xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_testing.dat +0 -15
  312. xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_yaml_example.yaml +0 -110
  313. xcoll/scattering_routines/geant4/collimasim/tests/resources/collgaps.dat +0 -7
  314. xcoll/scattering_routines/geant4/collimasim/tests/resources/collgaps_pyat_test.dat +0 -3
  315. xcoll/scattering_routines/geant4/collimasim/tests/resources/collonly_twiss_file_example.tfs +0 -54
  316. xcoll/scattering_routines/geant4/collimasim/tests/resources/settings.gmad +0 -3
  317. xcoll/scattering_routines/geant4/collimasim/tests/resources/settings_black_absorber.gmad +0 -3
  318. xcoll/scattering_routines/geant4/collimasim/tests/resources/settings_ions.gmad +0 -5
  319. xcoll/scattering_routines/geant4/collimasim/tests/resources/twiss_file_testing.tfs +0 -51
  320. xcoll/scattering_routines/geant4/collimasim/tests/test_pyat.py +0 -65
  321. xcoll/scattering_routines/geant4/collimasim/tests/test_pyat_passmethod.py +0 -59
  322. xcoll/scattering_routines/geant4/collimasim/tests/test_pyat_tracking.py +0 -102
  323. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack.py +0 -75
  324. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_angle.py +0 -74
  325. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_colldb_load.py +0 -84
  326. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_interaction.py +0 -159
  327. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_interaction_ion.py +0 -99
  328. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_ions.py +0 -78
  329. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_lost_energy.py +0 -88
  330. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_tilt.py +0 -80
  331. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_tracking.py +0 -97
  332. xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_tracking_ions.py +0 -96
  333. xcoll-0.5.12.dist-info/RECORD +0 -415
  334. {xcoll-0.5.12.dist-info → xcoll-0.6.1.dist-info}/LICENSE +0 -0
  335. {xcoll-0.5.12.dist-info → xcoll-0.6.1.dist-info}/NOTICE +0 -0
  336. {xcoll-0.5.12.dist-info → xcoll-0.6.1.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):