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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

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