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
@@ -1,122 +1,115 @@
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 os
7
7
  import numpy as np
8
- import shutil
8
+ from numbers import Number
9
+ from functools import wraps
9
10
 
10
11
  import xobjects as xo
11
- import xpart as xp
12
12
  import xtrack as xt
13
+ import xtrack.particles.pdg as pdg
14
+
13
15
  try:
14
16
  # TODO: once xaux is in Xsuite keep only this
15
- from xaux import ClassProperty, ClassPropertyMeta, FsPath, singleton
16
- except ImportError:
17
- from ..xaux import ClassProperty, ClassPropertyMeta, FsPath, singleton
18
-
17
+ from xaux import FsPath, ranID
18
+ except (ImportError, ModuleNotFoundError):
19
+ from ..xaux import FsPath, ranID
19
20
 
20
- class BaseEngineMeta(xo.hybrid_class.MetaHybridClass, ClassPropertyMeta):
21
- pass
22
21
 
23
- @singleton
24
- class BaseEngine(xo.HybridClass, metaclass=BaseEngineMeta):
22
+ class BaseEngine(xo.HybridClass):
25
23
  _xofields = {
26
- '_particle_ref': xp.Particles,
24
+ '_particle_ref': xt.Particles._XoStruct,
27
25
  '_seed': xo.UInt64,
28
26
  '_capacity': xo.Int64,
29
27
  }
30
28
 
31
29
  _int32 = False
32
- _element_classes = None
33
30
  _only_protons = False
31
+ _element_classes = None
34
32
  _uses_input_file = False
33
+ _num_input_files = 0
35
34
  _uses_run_folder = False
36
35
 
37
36
  def __init__(self, **kwargs):
38
- if not self._initialised:
39
- if np.any([key[0] != '_' for key in self._xofields.keys()]):
40
- raise ValueError(f"All fields in `{self.__class__.__name__}._xofields` have "
41
- + f"to start with an underscore! This is to ensure to work "
42
- + f"correctly with `ClassProperty`.")
43
- if '_xobject' not in kwargs:
44
- # Initialise defaults
45
- self._cwd = None
46
- self._line = None
47
- self._verbose = False
48
- self._input_file = None
49
- self._element_dict = {}
50
- self._warning_given = False
51
- self._tracking_initialised = False
52
- kwargs.setdefault('_particle_ref', xp.Particles())
53
- kwargs.setdefault('_seed', 0)
54
- kwargs.setdefault('_capacity', 0)
55
- filtered_kwargs = {}
56
- remaining_kwargs = {}
57
- for key, value in kwargs.items():
58
- if key in self._xofields.keys() or key == '_xobject':
59
- filtered_kwargs[key] = value
60
- else:
61
- remaining_kwargs[key] = value
62
- super().__init__(**filtered_kwargs)
63
- kwargs = remaining_kwargs
64
- self._initialised = True
65
- # Apply kwargs
66
- for kk, vv in kwargs.items():
67
- if not hasattr(self.__class__, kk):
68
- raise ValueError(f"Invalid attribute {kk} for {self.__class__.__name__}!")
69
- setattr(self, kk, vv)
37
+ if self._element_classes is None:
38
+ raise NotImplementedError(f"{self.__class__.__name__} needs to define `_element_classes`!")
39
+ # Initialise defaults
40
+ self._cwd = None
41
+ self._line = None
42
+ self._verbose = False
43
+ self._input_file = None
44
+ self._element_dict = {}
45
+ self._warning_given = False
46
+ self._environment = None
47
+ self._element_index = 0
48
+ self._tracking_initialised = False
49
+ self._deactivated_elements = {}
50
+ kwargs.setdefault('_particle_ref', xt.Particles())
51
+ kwargs.setdefault('_seed', 0)
52
+ kwargs.setdefault('_capacity', 0)
53
+ super().__init__(**kwargs)
70
54
 
71
55
  def __del__(self, *args, **kwargs):
72
56
  self.stop(warn=False)
73
57
 
74
-
75
58
  def _warn(self, error=None):
76
59
  if not self._warning_given:
77
60
  print(f"Warning: Failed to import {self.__class__.__name__} environment "
78
- + f" (did you compile?).\n{self.__class__.__name__.replace('Engine', '')} "
79
- + f"elements will be installed but are not trackable.\n", flush=True)
61
+ + f"(did you compile?).\n{self.name.capitalize()} elements can be installed "
62
+ + f"but are not trackable.", flush=True)
80
63
  if error:
81
- print(error, flush=True)
64
+ print(f"Error: {error}", flush=True)
82
65
  self._warning_given = True
66
+ self.stop()
67
+ if error:
68
+ raise error
69
+
70
+ def _print(self, *args, **kwargs):
71
+ if self.verbose:
72
+ kwargs.setdefault('flush', True)
73
+ print(*args, **kwargs)
83
74
 
84
75
 
85
76
  # ==================
86
77
  # === Properties ===
87
78
  # ==================
88
79
 
80
+ @property
81
+ def environment(self):
82
+ return self._environment
89
83
 
90
- @ClassProperty
91
- def name(cls):
92
- return cls.__name__.replace('Engine', '').lower()
84
+ @property
85
+ def name(self):
86
+ return self.__class__.__name__.replace('Engine', '').lower()
93
87
 
94
- @ClassProperty
95
- def verbose(cls):
96
- return cls.get_self()._verbose
88
+ @property
89
+ def verbose(self):
90
+ return self._verbose
97
91
 
98
92
  @verbose.setter
99
- def verbose(cls, val):
100
- cls.get_self()._verbose = val
93
+ def verbose(self, val):
94
+ self._verbose = val
101
95
 
102
- @ClassProperty
103
- def line(cls):
104
- return cls.get_self()._line
96
+ @property
97
+ def line(self):
98
+ return self._line
105
99
 
106
100
  @line.setter
107
- def line(cls, val):
101
+ def line(self, val):
108
102
  if not val is None and not isinstance(val, xt.Line):
109
103
  raise ValueError("`line` has to be an xt.Line object!")
110
- cls.get_self()._line = val
104
+ self._line = val
111
105
 
112
106
  @line.deleter
113
- def line(cls):
114
- cls.get_self()._line = None
107
+ def line(self):
108
+ self._line = None
115
109
 
116
- @ClassProperty
117
- def particle_ref(cls):
118
- self = cls.get_self()
119
- initial = xp.Particles().to_dict()
110
+ @property
111
+ def particle_ref(self):
112
+ initial = xt.Particles().to_dict()
120
113
  current = self._particle_ref.to_dict()
121
114
  if xt.line._dicts_equal(initial, current):
122
115
  return None
@@ -124,173 +117,274 @@ class BaseEngine(xo.HybridClass, metaclass=BaseEngineMeta):
124
117
  return self._particle_ref
125
118
 
126
119
  @particle_ref.setter
127
- def particle_ref(cls, val):
128
- self = cls.get_self()
120
+ def particle_ref(self, val):
129
121
  if val is None:
130
- self._particle_ref = xp.Particles()
122
+ self._particle_ref = xt.Particles()
131
123
  else:
132
- if not isinstance(val, xp.Particles):
133
- raise ValueError("`particle_ref` has to be an xp.Particles object!")
124
+ if not isinstance(val, xt.Particles):
125
+ raise ValueError("`particle_ref` has to be an xt.Particles object!")
134
126
  if val._capacity > 1:
135
127
  raise ValueError("`particle_ref` has to be a single particle!")
136
- if val.pdg_id[0] == 0:
137
- if cls._only_protons:
138
- val.pdg_id[0] = xp.get_pdg_id_from_name('proton')
128
+ pdg_id = val.pdg_id[0]
129
+ if pdg_id == 0:
130
+ if self._only_protons:
131
+ pdg_id = pdg.get_pdg_id_from_name('proton')
139
132
  else:
140
- raise ValueError("`particle_ref` needs to have a valid pdg_id")
141
- elif cls._only_protons and val.pdg_id[0] != xp.get_pdg_id_from_name('proton'):
142
- raise ValueError("{cls.__name__} only supports protons!")
133
+ raise ValueError(f"{self.__class__.__name__} allows the use of particles "
134
+ + f"different than protons. Hence, `particle_ref` "
135
+ + f"needs to have a valid pdg_id.")
136
+ elif self._only_protons and pdg_id != pdg.get_pdg_id_from_name('proton'):
137
+ raise ValueError("{self.__class__.__name__} only supports protons!")
143
138
  self._particle_ref = val
139
+ self._particle_ref.pdg_id[0] = pdg_id
144
140
 
145
141
  @particle_ref.deleter
146
- def particle_ref(cls):
147
- cls.get_self()._particle_ref = xp.Particles()
142
+ def particle_ref(self):
143
+ self.particle_ref = None
148
144
 
149
- @ClassProperty
150
- def capacity(cls):
151
- self = cls.get_self()
145
+ @property
146
+ def capacity(self):
152
147
  if self._capacity == 0:
153
148
  return None
154
149
  else:
155
150
  return int(self._capacity)
156
151
 
157
152
  @capacity.setter
158
- def capacity(cls, val):
153
+ def capacity(self, val):
159
154
  if val is None:
160
155
  val = 0
161
- cls.get_self()._capacity = int(val)
156
+ if not isinstance(val, Number) or val < 0:
157
+ raise ValueError("`capacity` has to be a positive integer!")
158
+ self._capacity = int(val)
162
159
 
163
160
  @capacity.deleter
164
- def capacity(cls):
165
- raise ValueError("Not allowed.")
161
+ def capacity(self):
162
+ self.capacity = None
166
163
 
167
- @ClassProperty
168
- def seed(cls):
169
- self = cls.get_self()
164
+ @property
165
+ def seed(self):
170
166
  if self._seed == 0:
171
167
  return None
172
168
  else:
173
169
  return self._seed
174
170
 
175
171
  @seed.setter
176
- def seed(cls, val):
172
+ def seed(self, val):
177
173
  if val is None:
178
174
  val = 0
175
+ if not isinstance(val, Number) or val < 0:
176
+ raise ValueError("`seed` has to be a positive integer!")
179
177
  val = int(val)
180
- if cls._int32:
178
+ if self._int32:
181
179
  new_val = np.uint32(val)
182
180
  else:
183
181
  new_val = np.uint64(val)
184
182
  if new_val != val:
185
- print(f"Warning: type change for seed {val}. Using {new_val}.")
186
- cls.get_self()._seed = new_val
183
+ self._print(f"Warning: type change for seed {val}. Using {new_val}.")
184
+ self._seed = new_val
187
185
 
188
186
  @seed.deleter
189
- def seed(cls):
190
- cls.get_self()._seed = 0
187
+ def seed(self):
188
+ self.seed = None
191
189
 
192
- @ClassProperty
193
- def input_file(cls):
194
- return cls.get_self()._input_file
190
+ @property
191
+ def input_file(self):
192
+ if self._uses_input_file:
193
+ return self._input_file
194
+
195
+ @property
196
+ def element_dict(self):
197
+ return self._element_dict
195
198
 
196
199
 
197
200
  # ======================
198
201
  # === Public Methods ===
199
202
  # ======================
200
203
 
201
-
202
- @classmethod
203
- def start(cls, *, line=None, elements=None, names=None, cwd=None, seed=None,
204
- particle_ref=None, input_file=None, **kwargs):
205
- self = cls.get_self(**kwargs)
206
- if self.is_running() is None:
207
- raise NotImplementedError(f"Need to implement `is_running` for {cls.__name__}!")
208
- elif self.is_running() is True:
209
- if self.verbose:
210
- print("Engine already running.", flush=True)
204
+ def start(self, *, clean=True, input_file=None, **kwargs):
205
+ if not self.environment:
206
+ raise RuntimeError(f"{self.name.capitalize()} environment not set up! "
207
+ + f"Do not manually create an instance of the engine.")
208
+ if not self.environment.initialised:
209
+ raise RuntimeError(f"{self.name.capitalize()} environment not initialised! "
210
+ + f"Please set all paths in the environment before "
211
+ + f"starting the engine.")
212
+ if not self.environment.compiled:
213
+ raise RuntimeError(f"{self.name.capitalize()} interface not compiled! "
214
+ + f"Please compile before starting the engine.")
215
+ if self.is_running():
216
+ self._print("Engine already running.")
211
217
  return
212
218
 
213
- self._starting_engine = True # We need this to allow changing the element settings which otherwise are locked
214
- self._use_seed(seed)
215
- self._use_line(line)
216
- self._use_particle_ref(particle_ref)
217
- self._sync_line_particle_ref()
218
- self._get_elements(line=line, elements=elements, names=names)
219
- self._set_cwd(cwd=cwd)
220
- self._use_input_file(input_file=input_file, **kwargs)
221
- self.clean_output_files()
222
- self._starting_engine = False
223
-
224
-
225
- @classmethod
226
- def stop(cls, clean=False, **kwargs):
227
- self = cls.get_self(**kwargs)
228
- if hasattr(self, '_old_seed'):
229
- self.seed = self._old_seed
230
- del self._old_seed
231
- if hasattr(self, '_old_line'):
232
- self.line = self._old_line
233
- del self._old_line
234
- if hasattr(self, '_old_particle_ref'):
235
- self.particle_ref = self._old_particle_ref
236
- del self._old_particle_ref
237
- self._sync_line_particle_ref()
238
- if hasattr(self, '_old_cwd') and self._old_cwd is not None:
239
- os.chdir(self._old_cwd)
240
- del self._old_cwd
219
+ # Clean up any leftover failed runs
220
+ self.stop(clean=clean)
221
+
222
+ print(f"Starting {self.__class__.__name__}... ", flush=True, end='')
223
+ kwargs = self._pre_start(**kwargs)
224
+
225
+ # This needs to be set in the ChildEngine, either in _start_engine() or at the start of tracking
226
+ self._tracking_initialised = False
227
+
228
+ # Set all engine properties that have a setter (this will remove these properties from the kwargs)
229
+ kwargs = self._set_engine_properties(**kwargs)
230
+
231
+ # Create input file if needed (this will remove the kwargs relevant to the input file and physics)
232
+ kwargs = self._use_input_file(input_file, **kwargs)
241
233
  if clean:
242
- self.clean_output_files(clean_all=True)
243
- self._cwd = None
244
- self._input_file = None
245
- self._element_dict = {}
234
+ self.clean_input_files(clean_all=False)
235
+ self._preparing_input = False
236
+
237
+ # Start the engine in the ChildEngine
238
+ self._start_engine(**kwargs)
239
+
240
+ # Done starting
241
+ if self.verbose:
242
+ print(f"{self.__class__.__name__} started.", flush=True)
243
+ else:
244
+ print(f"Done.", flush=True)
245
+
246
+ def stop(self, clean=False, **kwargs):
247
+ kwargs = self._stop_engine(**kwargs)
248
+ if clean:
249
+ self.clean(clean_all=True, **kwargs)
250
+ self._restore_engine_properties(clean=clean)
246
251
  self._warning_given = False
247
252
  self._tracking_initialised = False
248
253
 
249
254
 
250
- @classmethod
251
- def assert_particle_ref(cls, **kwargs):
252
- if cls.get_self(**kwargs).particle_ref is None:
253
- raise ValueError(f"{cls.__name__} reference particle not set!")
255
+ def assert_particle_ref(self):
256
+ if self.particle_ref is None:
257
+ raise ValueError(f"{self.__class__.__name__} reference particle not set!")
258
+
259
+
260
+ def generate_input_file(self, *, clean=True, filename=None, **kwargs):
261
+ # This method manually generates an input file without starting the engine
262
+ if not self._uses_input_file:
263
+ raise ValueError(f"{self.__class__.__name__} does not use input files!")
264
+ if self._element_dict:
265
+ raise ValueError("Elements already assigned to engine (cannot regenerate input "
266
+ + "file after starting engine)!")
267
+
268
+ # Set all engine properties that have a setter (this will remove these properties from the kwargs)
269
+ kwargs = self._set_engine_properties(**kwargs)
270
+
271
+ # Create input file
272
+ input_file, _ = self._generate_input_file(**kwargs)
273
+ if not hasattr(input_file, '__iter__') or isinstance(input_file, str):
274
+ # Some engines might need multiple input files (like Fluka)
275
+ input_file = [input_file]
276
+ if filename is None:
277
+ if hasattr(self, '_old_cwd') and self._old_cwd is not None:
278
+ input_file[0] = input_file[0].rename(self._old_cwd / input_file[0].name)
279
+ else:
280
+ input_file[0] = input_file[0].rename(filename)
281
+ for i, file in enumerate(input_file[1:]):
282
+ input_file[i+1] = file.rename(input_file[0].parent / file.name)
283
+ input_file = input_file[0] if self._num_input_files==1 else input_file
284
+
285
+ if clean:
286
+ self.clean_input_files(clean_all=False)
287
+ self._restore_engine_properties(clean=clean)
288
+
289
+ return input_file
290
+
291
+
292
+ def is_running(self):
293
+ if hasattr(self, '_preparing_input') and self._preparing_input:
294
+ # We need this to allow changing the element settings which otherwise are locked
295
+ return False
296
+ # If we get here, we cannot say if the engine is running or not and we need an
297
+ # implementation in the child class
298
+ return self._is_running()
299
+
300
+
301
+ def clean(self, **kwargs):
302
+ self.clean_input_files(**kwargs)
303
+ self.clean_output_files(**kwargs)
304
+
305
+ def clean_input_files(self, **kwargs):
306
+ kwargs = self._get_input_cwd_for_cleaning(**kwargs)
307
+ self._clean_input_files(**kwargs)
308
+
309
+ def clean_output_files(self, **kwargs):
310
+ kwargs = self._get_input_cwd_for_cleaning(**kwargs)
311
+ self._clean_output_files(**kwargs)
254
312
 
255
313
 
256
314
  # =======================
257
315
  # === Private Methods ===
258
316
  # =======================
259
317
 
260
- # For all the following fields, they can either be set in advance on the engine,
318
+ # For all the engine fields, they can either be set in advance on the engine,
261
319
  # or they can be set when the engine is started. In the latter case, the values
262
320
  # are temporary and the original will be restored when the engine is stopped.
263
321
 
264
- def _use_line(self, line=None):
265
- self._old_line = self.line
266
- self.line = line
322
+ def _set_engine_properties(self, **kwargs):
323
+ self._preparing_input = True # We need this to allow changing the element settings which otherwise are locked
324
+ def _set_property(prop):
325
+ val = kwargs.pop(prop, None)
326
+ if val is not None:
327
+ # We only need to update the property when it is not None
328
+ setattr(self, f'_old_{prop}', getattr(self, prop))
329
+ setattr(self, prop, val)
330
+ # We need to set the following properties first as they are needed by the others
331
+ _set_property('verbose')
332
+ _set_property('line')
333
+ # The following properties have a specific logic
334
+ self._use_seed(kwargs.pop('seed', None))
335
+ self._use_particle_ref(kwargs.pop('particle_ref', None))
336
+ self._sync_line_particle_ref()
337
+ self._get_elements(kwargs.pop('elements', None), kwargs.pop('names', None))
338
+ self._set_cwd(kwargs.pop('cwd', None))
339
+ # Now we can set the rest of the properties
340
+ _set_property('capacity')
341
+ return kwargs
342
+
343
+ def _restore_engine_properties(self, clean=False):
344
+ self._preparing_input = False
345
+ # Reset particle_ref in the line
346
+ if hasattr(self, '_old_particle_ref'):
347
+ self.line.particle_ref = self._old_line_particle_ref
348
+ del self._old_line_particle_ref
349
+ # The following properties have a specific logic
350
+ self._reactivate_elements()
351
+ self._reset_cwd(clean=clean)
352
+ # Reset all other properties
353
+ self_attributes = self.__dict__.copy()
354
+ for kk, vv in self_attributes.items():
355
+ if kk.startswith('_old_'):
356
+ prop = kk[5:]
357
+ setattr(self, prop, vv)
358
+ delattr(self, kk)
359
+ self._input_file = None
360
+ self._element_dict = {}
267
361
 
268
362
  def _use_seed(self, seed=None):
269
- self._old_seed = self.seed
270
- if seed is not None:
271
- self.seed = seed
272
- else:
363
+ if seed is None:
273
364
  if self.seed is None:
274
365
  if self._int32:
275
366
  self.seed = np.random.randint(0, int(2**32))
276
367
  else:
277
368
  self.seed = np.random.randint(0, int(2**64))
278
- if self.verbose:
279
- print(f"Using seed {self.seed}.")
369
+ else:
370
+ self._old_seed = self.seed
371
+ self.seed = seed
372
+ self._print(f"Using seed {self.seed}.")
280
373
 
281
374
  def _use_particle_ref(self, particle_ref=None):
282
375
  # Prefer: provided particle_ref > existing particle_ref > particle_ref from line
283
- self._old_particle_ref = self.particle_ref
284
376
  if particle_ref is not None:
377
+ self._old_particle_ref = self.particle_ref
285
378
  self.particle_ref = particle_ref
286
379
  elif self.particle_ref is None:
287
380
  if self.line is None or not hasattr(self.line, 'particle_ref') \
288
381
  or self.line.particle_ref is None:
289
382
  raise ValueError("Need to provide either a line with a reference "
290
383
  + "particle, or `particle_ref`.")
384
+ self._old_particle_ref = self.particle_ref
291
385
  self.particle_ref = self.line.particle_ref
292
- if self.verbose:
293
- print(f"Using {xp.get_name_from_pdg_id(self.particle_ref.pdg_id[0])}.")
386
+ self._print(f"Using {pdg.get_name_from_pdg_id(self.particle_ref.pdg_id[0])} "
387
+ + f"with momentum {self.particle_ref.p0c[0]/1.e9:.1f} GeV.")
294
388
 
295
389
  def _sync_line_particle_ref(self):
296
390
  if self.line is None:
@@ -298,68 +392,124 @@ class BaseEngine(xo.HybridClass, metaclass=BaseEngineMeta):
298
392
  if self.line.particle_ref is not None \
299
393
  and not xt.line._dicts_equal(self.line.particle_ref.to_dict(),
300
394
  self.particle_ref.to_dict()):
301
- overwrite_particle_ref_in_line = True
302
- if overwrite_particle_ref_in_line:
303
- print("Warning: Found different reference particle in line! Temporarily overwritten.")
395
+ self._print("Found different reference particle in line. Temporarily overwritten.")
396
+ self._old_line_particle_ref = self.line.particle_ref
304
397
  self.line.particle_ref = self.particle_ref
305
398
 
306
- def _get_elements(self, line=None, elements=None, names=None):
307
- if self._element_classes is None:
308
- raise NotImplementedError(f"{self.__class__.__name__} needs to define `_element_classes`!")
309
- if line is None:
399
+ def _get_new_element_name(self):
400
+ name = f"{self.name}_el_{self._element_index}"
401
+ self._element_index += 1
402
+ return name
403
+
404
+ def _deactivate_element(self, el):
405
+ self._deactivated_elements[el.name] = [el, el.active or True]
406
+ if hasattr(el, 'active'):
407
+ el.active = False
408
+ self._remove_element(el)
409
+
410
+ def _assert_element(self, element):
411
+ if not isinstance(element, self._element_classes):
412
+ raise ValueError(f"Element {element.name} is not a "
413
+ + ", or a ".join([c.__name__ for c in self._element_classes])
414
+ + ".")
415
+
416
+ def _get_elements(self, elements=None, names=None):
417
+ if elements is not None and (not hasattr(elements, '__iter__') or isinstance(elements, str)):
418
+ elements = [elements]
419
+ if names is not None and (not hasattr(names, '__iter__') or isinstance(names, str)):
420
+ names = [names]
421
+ if self.line is None:
310
422
  if elements is None:
311
423
  raise ValueError("Need to provide either `line` or `elements`.")
312
- if not hasattr(elements, '__iter__') or isinstance(elements, str):
313
- elements = [elements]
314
424
  if names is None:
315
- names = [f"{self.__class__.name}_el_{i}" for i, _ in enumerate(elements)]
425
+ names = []
426
+ for ee in elements:
427
+ if hasattr(ee, 'name'):
428
+ names.append(ee.name)
429
+ else:
430
+ name = self._get_new_element_name()
431
+ names.append(name)
432
+ ee.name = name
433
+ elif len(names) == len(elements):
434
+ for ee, name in zip(elements, names):
435
+ if hasattr(ee, 'name'):
436
+ if ee.name != name:
437
+ self._print(f"Warning: Element name {ee.name} changed to {name}.")
438
+ ee.name = name
316
439
  else:
317
- if not hasattr(names, '__iter__') or isinstance(names, str):
318
- names = [names]
319
- if len(names) != len(elements):
320
- raise ValueError("Length of `elements` and `names` doesn't match.")
440
+ raise ValueError("Length of `elements` and `names` doesn't match.")
321
441
  else:
322
442
  if elements is not None:
323
443
  raise ValueError("Cannot provide both `line` and `elements`.")
324
444
  if names is None:
325
- elements, names = line.get_elements_of_type(self._element_classes)
445
+ elements, names = self.line.get_elements_of_type(self._element_classes)
326
446
  else:
327
- if not hasattr(names, '__iter__') or isinstance(names, str):
328
- names = [names]
329
- elements = [line[name] for name in names]
330
- elements = [el for el in elements if el.active and el.jaw is not None]
331
- names = [name for el, name in zip(elements,names) if el.active and el.jaw is not None]
332
- for el in elements:
333
- if not isinstance(el, self._element_classes):
334
- raise ValueError(f"Element {el} is not a "
335
- + ", or a ".join([c.__name__ for c in self._element_classes])
336
- + ".")
337
- if len(elements) == 0:
447
+ elements = [self.line[name] for name in names]
448
+ this_names = []
449
+ this_elements = []
450
+ for ee, name in zip(elements, names):
451
+ self._assert_element(ee)
452
+ if ee.jaw is None:
453
+ self._print(f"Warning: Jaw not set for {name}. Ignoring.")
454
+ self._deactivate_element(ee)
455
+ elif not ee.active:
456
+ self._print(f"Warning: Element {name} is not active. Ignoring.")
457
+ self._deactivate_element(ee)
458
+ else:
459
+ this_names.append(name)
460
+ this_elements.append(ee)
461
+ if len(this_elements) == 0:
338
462
  raise ValueError(f"No active {self.name} elements found!")
339
- self._element_dict = dict(zip(names, elements))
463
+ self._element_dict = dict(zip(this_names, this_elements))
464
+
465
+ def _reactivate_elements(self):
466
+ names = list(self._deactivated_elements.keys())
467
+ for name in names:
468
+ ee, was_active = self._deactivated_elements.pop(name)
469
+ self._restore_element(ee)
470
+ if hasattr(ee, 'active'):
471
+ ee.active = was_active
340
472
 
341
- def _set_cwd(self, cwd):
473
+ def _set_cwd(self, cwd=None):
342
474
  if self._uses_run_folder:
343
475
  if cwd is not None:
344
476
  cwd = FsPath(cwd).expanduser().resolve()
477
+ if cwd.exists() and cwd != FsPath.cwd():
478
+ # Check if the folder already exists
479
+ # If the specified folder is the current one, we do not need to rename
480
+ i = 0
481
+ while (cwd.parent / f'{cwd.name}_{i:0>4}').exists():
482
+ i += 1
483
+ if i > 9999:
484
+ raise ValueError(f"Too many folders with the same "
485
+ + f"name {cwd}!")
486
+ cwd = cwd.parent / f'{cwd.name}_{i:0>4}'
345
487
  else:
346
- # TODO: use xaux.ranID here
347
- import base64
348
- ran = base64.urlsafe_b64encode(os.urandom(8)).decode('utf-8')
349
- ran_str = ''.join(c if c.isalnum() else 'X' for c in ran)
488
+ ran_str = ranID(only_alphanumeric=True)
350
489
  cwd = FsPath.cwd() / f'{self.name}_run_{ran_str}'
351
490
  self._cwd = cwd
352
491
  cwd.mkdir(parents=True, exist_ok=True)
353
492
  self._old_cwd = FsPath.cwd()
354
493
  os.chdir(cwd)
355
494
 
495
+ def _reset_cwd(self, clean=False):
496
+ if hasattr(self, '_old_cwd'):
497
+ if self._old_cwd is not None:
498
+ os.chdir(self._old_cwd)
499
+ if clean and self._cwd is not None and self._cwd != FsPath.cwd():
500
+ try:
501
+ self._cwd.rmdir()
502
+ except:
503
+ self._print(f"Warning: Failed to remove temporary folder "
504
+ + f"{self._cwd}.")
505
+ del self._old_cwd
506
+ self._cwd = None
507
+
508
+
356
509
  def _use_input_file(self, input_file=None, **kwargs):
357
510
  if self._uses_input_file:
358
511
  if input_file is None:
359
- if not hasattr(self, 'generate_input_file'):
360
- raise NotImplementedError("Need to implement `generate_input_file`"
361
- "for {cls.__name__}!")
362
- input_file = self.generate_input_file(**kwargs)
512
+ input_file, kwargs = self._generate_input_file(**kwargs)
363
513
  if not hasattr(input_file, '__iter__') or isinstance(input_file, str):
364
514
  # Some engines might need multiple input files (like Fluka)
365
515
  input_file = [input_file]
@@ -368,36 +518,83 @@ class BaseEngine(xo.HybridClass, metaclass=BaseEngineMeta):
368
518
  for file in input_file:
369
519
  if not file.exists():
370
520
  raise ValueError(f"Input file {file.as_posix()} not found!")
371
- if file.parent != FsPath.cwd():
372
- shutil.copy(file, FsPath.cwd())
521
+ if file.parent != FsPath.cwd() and self._uses_run_folder:
522
+ file.copy_to(FsPath.cwd(), method='mount')
373
523
  new_files.append(FsPath.cwd() / file.name)
374
524
  else:
375
525
  new_files.append(file)
376
- self._input_file = new_files[0] if len(new_files)==1 else new_files
526
+ self._input_file = new_files[0] if self._num_input_files==1 else new_files
377
527
  self._match_input_file()
528
+ return kwargs
529
+
530
+
531
+ def _get_input_cwd_for_cleaning(self, **kwargs):
532
+ # Get the input file and the cwd
533
+ input_file = kwargs.get('input_file', None)
534
+ cwd = kwargs.get('cwd', None)
535
+ if input_file is None:
536
+ if self.input_file is not None:
537
+ input_file = self.input_file
538
+ if cwd is None and self._cwd is not None:
539
+ cwd = self._cwd
540
+ else:
541
+ if not hasattr(input_file, '__iter__') or isinstance(input_file, str):
542
+ input_file = [input_file]
543
+ input_file = [FsPath(ff) for ff in input_file]
544
+ if cwd is None:
545
+ cwd = input_file[0].parent
546
+ if len(input_file) == 1:
547
+ input_file = input_file[0]
548
+ kwargs['input_file'] = input_file
549
+ if self._uses_run_folder:
550
+ kwargs['cwd'] = cwd
551
+ else:
552
+ kwargs['cwd'] = FsPath.cwd()
553
+ return kwargs
378
554
 
379
555
 
380
- # ===============================
381
- # === Methods to be inherited ===
382
- # ===============================
556
+ # =================================================
557
+ # === Methods to be overwritten by child engine ===
558
+ # =================================================
383
559
 
384
- @classmethod
385
- def is_running(cls, **kwargs):
386
- self = cls.get_self(**kwargs)
387
- if hasattr(self, '_starting_engine') and self._starting_engine:
388
- # We need this to allow changing the element settings which otherwise are locked
389
- return False
390
- # If we get here, we cannot say if the engine is running or not and we need an
391
- # implementation in the child class
392
- return None
560
+ def _start_engine(self, **kwargs):
561
+ raise NotImplementedError(f"Need to implement `_start_engine` for "
562
+ + f"{self.__class__.__name__}!")
393
563
 
394
- @classmethod
395
- def clean_output_files(cls, **kwargs):
396
- pass
564
+ def _stop_engine(self, **kwargs):
565
+ raise NotImplementedError(f"Need to implement `_stop_engine` for "
566
+ + f"{self.__class__.__name__}!")
567
+
568
+ def _is_running(self, **kwargs):
569
+ raise NotImplementedError(f"Need to implement `_is_running` for "
570
+ + f"{self.__class__.__name__}!")
397
571
 
398
572
  def _match_input_file(self, **kwargs):
399
- raise NotImplementedError("Need to implement `_match_input_file` for {cls.__name__}!")
573
+ if self._uses_input_file:
574
+ raise NotImplementedError(f"Need to implement `_match_input_file` for "
575
+ + f"{self.__class__.__name__}!")
576
+
577
+ def _generate_input_file(self, **kwargs):
578
+ if self._uses_input_file:
579
+ raise NotImplementedError("Need to implement `_generate_input_file` for "
580
+ + f"{self.__class__.__name__}!")
581
+
582
+
583
+ # ============================================================
584
+ # === Methods to be optionally overwritten by child engine ===
585
+ # ============================================================
586
+
587
+ def _clean_input_files(self, input_file=None, cwd=None, clean_all=False, **kwargs):
588
+ pass
589
+
590
+ def _clean_output_files(self, input_file=None, cwd=None, clean_all=False, **kwargs):
591
+ pass
592
+
593
+ def _remove_element(self, el):
594
+ pass
595
+
596
+ def _restore_element(self, el):
597
+ pass
400
598
 
401
- @classmethod
402
- def generate_input_file(cls, **kwargs):
403
- raise NotImplementedError("Need to implement `generate_input_file` for {cls.__name__}!")
599
+ def _pre_start(self, **kwargs):
600
+ return kwargs