xcoll 0.3.6__py3-none-any.whl → 0.5.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.
- xcoll/__init__.py +13 -4
- xcoll/beam_elements/__init__.py +14 -6
- xcoll/beam_elements/absorber.py +41 -7
- xcoll/beam_elements/base.py +1202 -247
- xcoll/beam_elements/blowup.py +198 -0
- xcoll/beam_elements/elements_src/black_absorber.h +136 -0
- xcoll/beam_elements/elements_src/black_crystal.h +129 -0
- xcoll/beam_elements/elements_src/blowup.h +42 -0
- xcoll/beam_elements/elements_src/emittance_monitor.h +109 -0
- xcoll/beam_elements/{collimators_src → elements_src}/everest_block.h +59 -30
- xcoll/beam_elements/elements_src/everest_collimator.h +237 -0
- xcoll/beam_elements/elements_src/everest_crystal.h +280 -0
- xcoll/beam_elements/everest.py +65 -119
- xcoll/beam_elements/monitor.py +428 -0
- xcoll/colldb.py +276 -747
- xcoll/general.py +5 -5
- xcoll/headers/checks.h +1 -1
- xcoll/headers/particle_states.h +2 -2
- xcoll/initial_distribution.py +207 -0
- xcoll/install.py +179 -0
- xcoll/interaction_record/__init__.py +1 -0
- xcoll/interaction_record/interaction_record.py +298 -0
- xcoll/interaction_record/interaction_record_src/interaction_record.h +98 -0
- xcoll/{impacts → interaction_record}/interaction_types.py +11 -4
- xcoll/line_tools.py +82 -0
- xcoll/lossmap.py +219 -0
- xcoll/manager.py +2 -937
- xcoll/rf_sweep.py +1 -1
- xcoll/scattering_routines/everest/amorphous.h +232 -0
- xcoll/scattering_routines/everest/channeling.h +240 -0
- xcoll/scattering_routines/everest/crystal_parameters.h +137 -0
- xcoll/scattering_routines/everest/everest.h +11 -30
- xcoll/scattering_routines/everest/everest.py +13 -10
- xcoll/scattering_routines/everest/jaw.h +28 -197
- xcoll/scattering_routines/everest/materials.py +37 -15
- xcoll/scattering_routines/everest/multiple_coulomb_scattering.h +31 -10
- xcoll/scattering_routines/everest/nuclear_interaction.h +86 -0
- xcoll/scattering_routines/everest/properties.h +6 -1
- xcoll/scattering_routines/fluka/flukaio/lib/libFlukaIO64.a +0 -0
- xcoll/scattering_routines/geant4/collimasim/.git +1 -0
- xcoll/scattering_routines/geant4/collimasim/.gitignore +12 -0
- xcoll/scattering_routines/geant4/collimasim/.gitmodules +3 -0
- xcoll/scattering_routines/geant4/collimasim/CMakeLists.txt +26 -0
- xcoll/scattering_routines/geant4/collimasim/README.md +21 -0
- xcoll/scattering_routines/geant4/collimasim/docs/Makefile +20 -0
- xcoll/scattering_routines/geant4/collimasim/docs/make.bat +35 -0
- xcoll/scattering_routines/geant4/collimasim/docs/source/collimasim.rst +10 -0
- xcoll/scattering_routines/geant4/collimasim/docs/source/conf.py +59 -0
- xcoll/scattering_routines/geant4/collimasim/docs/source/index.rst +26 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.appveyor.yml +37 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.clang-format +19 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.clang-tidy +65 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.cmake-format.yaml +73 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.git +1 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/CODEOWNERS +9 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/CONTRIBUTING.md +386 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/ISSUE_TEMPLATE/bug-report.yml +45 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/ISSUE_TEMPLATE/config.yml +8 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/dependabot.yml +16 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/labeler.yml +8 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/labeler_merged.yml +3 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/pull_request_template.md +19 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/ci.yml +969 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/configure.yml +84 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/format.yml +48 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/labeler.yml +16 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.github/workflows/pip.yml +103 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.gitignore +45 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.pre-commit-config.yaml +151 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/.readthedocs.yml +3 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/CMakeLists.txt +297 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/LICENSE +29 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/MANIFEST.in +6 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/README.rst +180 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/Doxyfile +23 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/Makefile +192 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/_static/theme_overrides.css +11 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/chrono.rst +81 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/custom.rst +93 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/eigen.rst +310 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/functional.rst +109 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/index.rst +43 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/overview.rst +171 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/stl.rst +251 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/cast/strings.rst +305 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/classes.rst +1297 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/embedding.rst +262 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/exceptions.rst +396 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/functions.rst +568 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/misc.rst +337 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/pycpp/index.rst +13 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/pycpp/numpy.rst +463 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/pycpp/object.rst +286 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/pycpp/utilities.rst +155 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/advanced/smart_ptrs.rst +174 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/basics.rst +308 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/benchmark.py +91 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/benchmark.rst +95 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/changelog.rst +2050 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/classes.rst +542 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/cmake/index.rst +8 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/compiling.rst +648 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/conf.py +381 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/faq.rst +343 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/index.rst +48 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/installing.rst +105 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/limitations.rst +72 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11-logo.png +0 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11_vs_boost_python1.png +0 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11_vs_boost_python1.svg +427 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11_vs_boost_python2.png +0 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/pybind11_vs_boost_python2.svg +427 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/reference.rst +130 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/release.rst +96 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/requirements.txt +8 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/docs/upgrade.rst +548 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/attr.h +605 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/buffer_info.h +144 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/cast.h +1432 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/chrono.h +213 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/common.h +2 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/complex.h +65 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/class.h +709 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/common.h +1021 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/descr.h +104 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/init.h +346 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/internals.h +467 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/type_caster_base.h +978 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/detail/typeid.h +55 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/eigen.h +606 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/embed.h +284 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/eval.h +163 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/functional.h +121 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/gil.h +193 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/iostream.h +275 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/numpy.h +1741 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/operators.h +163 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/options.h +65 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/pybind11.h +2497 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/pytypes.h +1879 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/stl/filesystem.h +103 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/stl.h +375 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/include/pybind11/stl_bind.h +747 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/noxfile.py +88 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/__init__.py +11 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/__main__.py +52 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/_version.py +12 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/_version.pyi +6 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/commands.py +21 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/py.typed +0 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/setup_helpers.py +482 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pybind11/setup_helpers.pyi +63 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/pyproject.toml +41 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/setup.cfg +56 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/setup.py +155 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/CMakeLists.txt +503 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/conftest.py +208 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/constructor_stats.h +275 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/cross_module_gil_utils.cpp +73 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/env.py +33 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/extra_python_package/pytest.ini +0 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/extra_python_package/test_files.py +279 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/extra_setuptools/pytest.ini +0 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/extra_setuptools/test_setuphelper.py +143 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/local_bindings.h +85 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/object.h +179 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/pybind11_cross_module_tests.cpp +151 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/pybind11_tests.cpp +91 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/pybind11_tests.h +85 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/pytest.ini +19 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/requirements.txt +12 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_async.cpp +26 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_async.py +25 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_buffers.cpp +216 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_buffers.py +163 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_builtin_casters.cpp +286 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_builtin_casters.py +536 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_call_policies.cpp +107 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_call_policies.py +248 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_callbacks.cpp +227 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_callbacks.py +202 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_chrono.cpp +84 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_chrono.py +210 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_class.cpp +550 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_class.py +473 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/CMakeLists.txt +84 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/embed.cpp +21 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/installed_embed/CMakeLists.txt +28 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/installed_function/CMakeLists.txt +39 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/installed_target/CMakeLists.txt +46 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/main.cpp +6 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt +41 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/subdirectory_function/CMakeLists.txt +35 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/subdirectory_target/CMakeLists.txt +41 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_cmake_build/test.py +10 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_constants_and_functions.cpp +165 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_constants_and_functions.py +53 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_copy_move.cpp +238 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_copy_move.py +126 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_custom_type_casters.cpp +141 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_custom_type_casters.py +117 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_custom_type_setup.cpp +41 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_custom_type_setup.py +50 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_docstring_options.cpp +69 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_docstring_options.py +42 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eigen.cpp +348 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eigen.py +771 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/CMakeLists.txt +47 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/catch.cpp +22 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/external_module.cpp +23 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/test_interpreter.cpp +326 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_embed/test_interpreter.py +15 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_enum.cpp +148 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_enum.py +272 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eval.cpp +119 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eval.py +51 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_eval_call.py +5 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_exceptions.cpp +285 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_exceptions.h +12 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_exceptions.py +265 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_factory_constructors.cpp +397 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_factory_constructors.py +520 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_gil_scoped.cpp +49 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_gil_scoped.py +94 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_iostream.cpp +125 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_iostream.py +331 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_kwargs_and_defaults.cpp +153 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_kwargs_and_defaults.py +284 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_local_bindings.cpp +107 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_local_bindings.py +257 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_methods_and_attributes.cpp +412 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_methods_and_attributes.py +517 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_modules.cpp +102 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_modules.py +92 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_multiple_inheritance.cpp +233 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_multiple_inheritance.py +360 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_array.cpp +472 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_array.py +593 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_dtypes.cpp +524 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_dtypes.py +441 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_vectorize.cpp +103 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_numpy_vectorize.py +267 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_opaque_types.cpp +73 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_opaque_types.py +59 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_operator_overloading.cpp +235 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_operator_overloading.py +146 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_pickling.cpp +189 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_pickling.py +82 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_pytypes.cpp +560 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_pytypes.py +651 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_sequences_and_iterators.cpp +500 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_sequences_and_iterators.py +253 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_smart_ptr.cpp +452 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_smart_ptr.py +318 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_stl.cpp +342 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_stl.py +291 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_stl_binders.cpp +131 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_stl_binders.py +318 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_tagbased_polymorphic.cpp +144 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_tagbased_polymorphic.py +29 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_thread.cpp +66 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_thread.py +44 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_union.cpp +22 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_union.py +9 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_virtual_functions.cpp +510 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/test_virtual_functions.py +408 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/valgrind-numpy-scipy.supp +140 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tests/valgrind-python.supp +117 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/FindCatch.cmake +70 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/FindEigen3.cmake +86 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/FindPythonLibsNew.cmake +257 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/check-style.sh +44 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/cmake_uninstall.cmake.in +23 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/libsize.py +39 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/make_changelog.py +64 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pybind11Common.cmake +402 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pybind11Config.cmake.in +233 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pybind11NewTools.cmake +276 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pybind11Tools.cmake +214 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/pyproject.toml +3 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/setup_global.py.in +65 -0
- xcoll/scattering_routines/geant4/collimasim/lib/pybind11/tools/setup_main.py.in +41 -0
- xcoll/scattering_routines/geant4/collimasim/pyproject.toml +8 -0
- xcoll/scattering_routines/geant4/collimasim/setup.py +144 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim/BDSPyATInterface.cpp +403 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim/BDSPyATInterface.hh +100 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim/BDSXtrackInterface.cpp +763 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim/BDSXtrackInterface.hh +118 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim/__init__.py +8 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim/bindings.cpp +63 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim/pyCollimatorPass.py +142 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim/xtrack_collimator.py +556 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/PKG-INFO +6 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/SOURCES.txt +24 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/dependency_links.txt +1 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/not-zip-safe +1 -0
- xcoll/scattering_routines/geant4/collimasim/src/collimasim.egg-info/top_level.txt +1 -0
- xcoll/scattering_routines/geant4/collimasim/tests/README.md +25 -0
- xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_forions.dat +25 -0
- xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_new_example.dat +18 -0
- xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_old_example.dat +68 -0
- xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_testing.dat +15 -0
- xcoll/scattering_routines/geant4/collimasim/tests/resources/CollDB_yaml_example.yaml +110 -0
- xcoll/scattering_routines/geant4/collimasim/tests/resources/collgaps.dat +7 -0
- xcoll/scattering_routines/geant4/collimasim/tests/resources/collgaps_pyat_test.dat +3 -0
- xcoll/scattering_routines/geant4/collimasim/tests/resources/collonly_twiss_file_example.tfs +54 -0
- xcoll/scattering_routines/geant4/collimasim/tests/resources/settings.gmad +3 -0
- xcoll/scattering_routines/geant4/collimasim/tests/resources/settings_black_absorber.gmad +3 -0
- xcoll/scattering_routines/geant4/collimasim/tests/resources/settings_ions.gmad +5 -0
- xcoll/scattering_routines/geant4/collimasim/tests/resources/twiss_file_testing.tfs +51 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_pyat.py +65 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_pyat_passmethod.py +59 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_pyat_tracking.py +102 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack.py +75 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_angle.py +74 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_colldb_load.py +84 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_interaction.py +159 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_interaction_ion.py +99 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_ions.py +78 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_lost_energy.py +88 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_tilt.py +80 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_tracking.py +97 -0
- xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_tracking_ions.py +96 -0
- xcoll/scattering_routines/geometry/__init__.py +6 -0
- xcoll/scattering_routines/geometry/collimator_geometry.h +218 -0
- xcoll/scattering_routines/geometry/crystal_geometry.h +153 -0
- xcoll/scattering_routines/geometry/geometry.py +26 -0
- xcoll/scattering_routines/geometry/get_s.h +92 -0
- xcoll/scattering_routines/geometry/methods.h +111 -0
- xcoll/scattering_routines/geometry/objects.h +154 -0
- xcoll/scattering_routines/geometry/rotation.h +23 -0
- xcoll/scattering_routines/geometry/segments.h +226 -0
- xcoll/scattering_routines/geometry/sort.h +184 -0
- {xcoll-0.3.6.dist-info → xcoll-0.5.0.dist-info}/METADATA +1 -1
- xcoll-0.5.0.dist-info/RECORD +413 -0
- xcoll/beam_elements/collimators_src/absorber.h +0 -141
- xcoll/beam_elements/collimators_src/everest_collimator.h +0 -142
- xcoll/beam_elements/collimators_src/everest_crystal.h +0 -115
- xcoll/collimator_settings.py +0 -457
- xcoll/impacts/__init__.py +0 -1
- xcoll/impacts/impacts.py +0 -102
- xcoll/impacts/impacts_src/impacts.h +0 -99
- xcoll/scattering_routines/everest/crystal.h +0 -1302
- xcoll/scattering_routines/everest/scatter.h +0 -169
- xcoll/scattering_routines/everest/scatter_crystal.h +0 -260
- xcoll/scattering_routines/fluka/build_fluka_input.py +0 -58
- xcoll-0.3.6.dist-info/RECORD +0 -111
- {xcoll-0.3.6.dist-info → xcoll-0.5.0.dist-info}/LICENSE +0 -0
- {xcoll-0.3.6.dist-info → xcoll-0.5.0.dist-info}/NOTICE +0 -0
- {xcoll-0.3.6.dist-info → xcoll-0.5.0.dist-info}/WHEEL +0 -0
xcoll/colldb.py
CHANGED
|
@@ -1,33 +1,32 @@
|
|
|
1
1
|
# copyright ############################### #
|
|
2
2
|
# This file is part of the Xcoll Package. #
|
|
3
|
-
# Copyright (c) CERN,
|
|
3
|
+
# Copyright (c) CERN, 2024. #
|
|
4
4
|
# ######################################### #
|
|
5
5
|
|
|
6
6
|
import io
|
|
7
|
+
import re
|
|
7
8
|
import json
|
|
8
9
|
import numpy as np
|
|
9
10
|
import pandas as pd
|
|
11
|
+
from pathlib import Path
|
|
10
12
|
|
|
13
|
+
import xtrack as xt
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
from .beam_elements import BlackAbsorber, BlackCrystal, EverestCollimator, EverestCrystal, \
|
|
16
|
+
BaseCollimator, BaseCrystal, _all_collimator_classes
|
|
17
|
+
from .install import install_elements
|
|
18
|
+
from .scattering_routines.everest.materials import SixTrack_to_xcoll
|
|
13
19
|
|
|
14
|
-
def load_SixTrack_colldb(filename, *, emit):
|
|
15
|
-
print("Warning: Using 'xcoll.load_SixTrack_colldb()' is deprecated! "
|
|
16
|
-
+ "Use 'xcoll.CollimatorDatabase.from_SixTrack()' instead.")
|
|
17
|
-
return CollimatorDatabase.from_SixTrack(file=filename, nemitt_x=emit, nemitt_y=emit)
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
fields
|
|
22
|
-
fields.update({'
|
|
23
|
-
fields.update({'
|
|
24
|
-
fields.update({'side': 'both', 'material': None, 'stage': None, 'collimator_type': None, 'active': True})
|
|
25
|
-
fields.update({'active_length': 0, 'inactive_front': 0, 'inactive_back': 0, 'sigmax': None, 'sigmay': None})
|
|
26
|
-
fields.update({'crystal': None, 'bending_radius': None, 'xdim': 0, 'ydim': 0, 'miscut': 0, 'thick': 0})
|
|
21
|
+
def _initialise_None(dct):
|
|
22
|
+
fields = {'gap': None, 'angle': 0, 'offset': 0, 'parking': 1, 'jaw': None, 'family': None}
|
|
23
|
+
fields.update({'overwritten_keys': [], 'side': 'both', 'material': None, 'stage': None})
|
|
24
|
+
fields.update({'length': 0, 'collimator_type': None, 'active': True, 'crystal': None, 'tilt': 0})
|
|
25
|
+
fields.update({'bending_radius': None, 'bending_angle': None, 'width': 0, 'height': 0, 'miscut': 0})
|
|
27
26
|
for f, val in fields.items():
|
|
28
|
-
if f not in
|
|
29
|
-
|
|
30
|
-
for key in
|
|
27
|
+
if f not in dct.keys():
|
|
28
|
+
dct[f] = val
|
|
29
|
+
for key in dct.keys():
|
|
31
30
|
if key not in fields.keys():
|
|
32
31
|
raise ValueError(f"Illegal setting {key} in collimator!")
|
|
33
32
|
|
|
@@ -47,7 +46,7 @@ def _get_coll_dct_by_beam(coll, beam):
|
|
|
47
46
|
beam = f'b{beam}'
|
|
48
47
|
beam = beam.lower()
|
|
49
48
|
beam_in_db = list(coll.keys())
|
|
50
|
-
|
|
49
|
+
|
|
51
50
|
if beam_in_db == ['b1','b2']:
|
|
52
51
|
if beam is None:
|
|
53
52
|
raise ValueError("Need to specify a beam, because the given dict is for both beams!")
|
|
@@ -67,16 +66,90 @@ def _get_coll_dct_by_beam(coll, beam):
|
|
|
67
66
|
|
|
68
67
|
class CollimatorDatabase:
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
def __init__(self, **kwargs):
|
|
70
|
+
# Get all arguments
|
|
71
|
+
for key in ['collimator_dict', 'nemitt_x', 'nemitt_y']:
|
|
72
|
+
if key not in kwargs.keys():
|
|
73
|
+
raise ValueError(f"CollimatorDatabase is missing required argument '{key}'!")
|
|
74
|
+
|
|
75
|
+
self._parse_dict(kwargs['collimator_dict'],
|
|
76
|
+
kwargs.get('family_dict', {}),
|
|
77
|
+
kwargs.get('beam', None),
|
|
78
|
+
kwargs.get('_yaml_merged', False),
|
|
79
|
+
kwargs.get('ignore_crystals', True))
|
|
80
|
+
self.nemitt_x = kwargs['nemitt_x']
|
|
81
|
+
self.nemitt_y = kwargs['nemitt_y']
|
|
82
|
+
self._elements = {}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _parse_dict(self, coll, fam, beam=None, _yaml_merged=False, ignore_crystals=True):
|
|
86
|
+
# We make all keys case-insensitive to avoid confusion between different conventions
|
|
87
|
+
coll = _dict_keys_to_lower(coll)
|
|
88
|
+
fam = _dict_keys_to_lower(fam)
|
|
89
|
+
|
|
90
|
+
# The dictionary can be a CollimatorDatabase for a single beam (beam=None)
|
|
91
|
+
# or for both beams (beam='b1' or beam='b2)
|
|
92
|
+
coll = _get_coll_dct_by_beam(coll, beam)
|
|
93
|
+
|
|
94
|
+
# Apply family settings
|
|
95
|
+
crystals = []
|
|
96
|
+
for thiscoll, settings in coll.items():
|
|
97
|
+
settings = {k.lower(): v for k,v in settings.items()}
|
|
98
|
+
if 'family' in settings.keys() and settings['family'] is not None:
|
|
99
|
+
settings['family'] = settings['family'].lower()
|
|
100
|
+
thisfam = settings['family']
|
|
101
|
+
if thisfam not in fam.keys():
|
|
102
|
+
raise ValueError(f"Collimator {thiscoll} depends on family {thisfam}, "
|
|
103
|
+
+ f"but the latter is not defined!")
|
|
104
|
+
|
|
105
|
+
# Check if some family settings are overwritten for this collimator
|
|
106
|
+
# Only do this check if we didn't do a YAML merge earlier (because then it
|
|
107
|
+
# is already taken care of)
|
|
108
|
+
if not _yaml_merged:
|
|
109
|
+
overwritten_keys = [key.lower() for key in settings.keys() if key in fam[thisfam]]
|
|
110
|
+
if len(overwritten_keys) > 0:
|
|
111
|
+
settings['overwritten_keys'] = overwritten_keys
|
|
112
|
+
|
|
113
|
+
# Load family settings, potentially overwriting settings for this collimator
|
|
114
|
+
settings = {**fam[thisfam], **settings}
|
|
115
|
+
|
|
116
|
+
else:
|
|
117
|
+
settings['family'] = None
|
|
118
|
+
coll[thiscoll] = settings
|
|
119
|
+
|
|
120
|
+
# Save list of crystals
|
|
121
|
+
if 'crystal' in settings:
|
|
122
|
+
if settings['crystal'] != 0.0:
|
|
123
|
+
crystals += [thiscoll]
|
|
124
|
+
else:
|
|
125
|
+
settings['crystal'] = None
|
|
126
|
+
|
|
127
|
+
# Remove crystals from colldb
|
|
128
|
+
if ignore_crystals:
|
|
129
|
+
for thiscoll in crystals:
|
|
130
|
+
del coll[thiscoll]
|
|
131
|
+
|
|
132
|
+
# Check that all collimators have gap settings
|
|
133
|
+
if not np.all(['gap' in val.keys() or 'jaw' in val.keys() for val in coll.values()]):
|
|
134
|
+
raise ValueError("Ill-defined CollimatorDatabase: Not all collimators have a gap or "
|
|
135
|
+
+ "jaw setting, (or the keys / structure of the dictionary is wrong)!")
|
|
136
|
+
|
|
137
|
+
# Update collimators with default values for missing keys
|
|
138
|
+
for name, collimator in coll.items():
|
|
139
|
+
# Change all values to lower case
|
|
140
|
+
for key, val in collimator.items():
|
|
141
|
+
collimator[key] = val.lower() if isinstance(val, str) else val
|
|
142
|
+
_initialise_None(collimator)
|
|
143
|
+
|
|
144
|
+
self._collimator_dict = coll
|
|
145
|
+
self._family_dict = fam
|
|
146
|
+
|
|
147
|
+
# =======================================
|
|
148
|
+
# ====== Loading/dumping functions ======
|
|
149
|
+
# =======================================
|
|
72
150
|
|
|
73
|
-
# -------------------------------
|
|
74
|
-
# ------ Loading functions ------
|
|
75
|
-
# -------------------------------
|
|
76
|
-
|
|
77
151
|
@classmethod
|
|
78
152
|
def from_yaml(cls, file, **kwargs):
|
|
79
|
-
|
|
80
153
|
# Only do the import here, as to not force people to install
|
|
81
154
|
# ruamel if they don't load CollimatorDatabase yaml's
|
|
82
155
|
from ruamel.yaml import YAML
|
|
@@ -84,7 +157,8 @@ class CollimatorDatabase:
|
|
|
84
157
|
if isinstance(file, io.IOBase):
|
|
85
158
|
dct = yaml.load(file)
|
|
86
159
|
else:
|
|
87
|
-
|
|
160
|
+
file = Path(file).resolve()
|
|
161
|
+
with file.open('r') as fid:
|
|
88
162
|
dct = yaml.load(fid)
|
|
89
163
|
dct = _dict_keys_to_lower(dct)
|
|
90
164
|
|
|
@@ -119,6 +193,8 @@ class CollimatorDatabase:
|
|
|
119
193
|
coll_dct = _get_coll_dct_by_beam(dct['collimators'], beam)
|
|
120
194
|
full_coll_dct = _get_coll_dct_by_beam(full_dct[collkey], beam)
|
|
121
195
|
for coll, full_coll in zip(coll_dct.values(), full_coll_dct.values()):
|
|
196
|
+
if not isinstance(coll['gap'], (int,float)):
|
|
197
|
+
coll['gap'] = None
|
|
122
198
|
if 'family' in coll.keys():
|
|
123
199
|
raise ValueError(f"Error in {coll}: Cannot use merging for families "
|
|
124
200
|
+ "and manually specify family as well!")
|
|
@@ -141,7 +217,8 @@ class CollimatorDatabase:
|
|
|
141
217
|
if isinstance(file, io.IOBase):
|
|
142
218
|
dct = json.load(file)
|
|
143
219
|
else:
|
|
144
|
-
|
|
220
|
+
file = Path(file).resolve()
|
|
221
|
+
with file.open('r') as fid:
|
|
145
222
|
dct = json.load(fid)
|
|
146
223
|
dct = _dict_keys_to_lower(dct)
|
|
147
224
|
return cls.from_dict(dct, **kwargs)
|
|
@@ -186,17 +263,16 @@ class CollimatorDatabase:
|
|
|
186
263
|
|
|
187
264
|
@classmethod
|
|
188
265
|
def from_SixTrack(cls, file, ignore_crystals=True, **kwargs):
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
with open(file, 'r') as infile:
|
|
266
|
+
file = Path(file).resolve()
|
|
267
|
+
with file.open('r') as fp:
|
|
192
268
|
coll_data_string = ''
|
|
193
269
|
family_settings = {}
|
|
194
270
|
family_types = {}
|
|
195
271
|
side = {}
|
|
196
|
-
cry_fields = ['bending_radius', '
|
|
272
|
+
cry_fields = ['bending_radius', 'width', 'height', 'thick', 'tilt', 'miscut', 'crystal']
|
|
197
273
|
cry = {}
|
|
198
274
|
|
|
199
|
-
for
|
|
275
|
+
for line in fp:
|
|
200
276
|
if line.startswith('#'):
|
|
201
277
|
continue # Comment
|
|
202
278
|
sline = line.split()
|
|
@@ -209,8 +285,8 @@ class CollimatorDatabase:
|
|
|
209
285
|
elif sline[0].lower() == "crystal":
|
|
210
286
|
cry[sline[1]] = {}
|
|
211
287
|
for i, key in enumerate(cry_fields):
|
|
212
|
-
idx = i+2
|
|
213
|
-
if i <
|
|
288
|
+
idx = i+2
|
|
289
|
+
if i < 6:
|
|
214
290
|
cry[sline[1]][key] = float(sline[idx])
|
|
215
291
|
else:
|
|
216
292
|
cry[sline[1]][key] = int(sline[idx])
|
|
@@ -224,16 +300,20 @@ class CollimatorDatabase:
|
|
|
224
300
|
|
|
225
301
|
defaults = {}
|
|
226
302
|
_initialise_None(defaults)
|
|
303
|
+
defaults['thick'] = 0
|
|
227
304
|
|
|
228
|
-
famdct = {key: {'gap':
|
|
229
|
-
|
|
305
|
+
famdct = {key: {'gap': None if family_settings[key] > 900 else family_settings[key],
|
|
306
|
+
'stage': family_types[key]} for key in family_settings}
|
|
307
|
+
names = ['name', 'gap', 'material', 'length', 'angle', 'offset']
|
|
230
308
|
|
|
231
309
|
df = pd.read_csv(io.StringIO(coll_data_string), sep=r'\s+', index_col=False, names=names)
|
|
232
310
|
df['family'] = df['gap'].copy()
|
|
233
311
|
df['family'] = df['family'].apply(lambda s: None if re.match(r'^-?\d+(\.\d+)?$', str(s)) else s)
|
|
234
|
-
df.insert(5,'stage', df['gap'].apply(lambda s:
|
|
312
|
+
df.insert(5,'stage', df['gap'].apply(lambda s: None if s in family_types else 'UNKNOWN'))
|
|
313
|
+
|
|
314
|
+
df['gap'] = df['gap'].apply(lambda s: None if not isinstance(s, str) and s > 900 else s)
|
|
315
|
+
df['gap'] = df['gap'].apply(lambda s: None if isinstance(s, str) else s)
|
|
235
316
|
|
|
236
|
-
df['gap'] = df['gap'].apply(lambda s: float(family_settings.get(s, s)))
|
|
237
317
|
# TODO this breaks code if a key has upper case, e.g. gap_L
|
|
238
318
|
df['name'] = df['name'].str.lower() # Make the names lowercase for easy processing
|
|
239
319
|
df['parking'] = 0.025
|
|
@@ -243,6 +323,9 @@ class CollimatorDatabase:
|
|
|
243
323
|
for key in cry_fields:
|
|
244
324
|
df[key] = [cry[name][key] if name in cry else defaults[key]
|
|
245
325
|
for name in df['name']]
|
|
326
|
+
if not np.allclose(np.unique(df.thick.values), 0):
|
|
327
|
+
print("Warning: Keyword 'thick' is currently not supported in xcoll! Ignoring.")
|
|
328
|
+
df = df.drop('thick', axis=1)
|
|
246
329
|
df['crystal'] = ['strip' if s==1 else s for s in df['crystal']]
|
|
247
330
|
df['crystal'] = ['quasi-mosaic' if s==2 else s for s in df['crystal']]
|
|
248
331
|
df['side'] = [side[name] if name in side else defaults['side']
|
|
@@ -250,13 +333,32 @@ class CollimatorDatabase:
|
|
|
250
333
|
df['side'] = ['both' if s==0 else s for s in df['side']]
|
|
251
334
|
df['side'] = ['left' if s==1 else s for s in df['side']]
|
|
252
335
|
df['side'] = ['right' if s==2 else s for s in df['side']]
|
|
336
|
+
if not np.allclose(np.unique(df.offset.values), 0):
|
|
337
|
+
print("Warning: Keyword 'offset' is currently not supported in xcoll! Ignoring.")
|
|
338
|
+
df = df.drop('offset', axis=1)
|
|
253
339
|
df = df.set_index('name')
|
|
254
|
-
|
|
255
|
-
|
|
340
|
+
df = df.replace(np.nan, None)
|
|
341
|
+
|
|
342
|
+
colldict = df.transpose().to_dict()
|
|
343
|
+
# Remove Nonetype families
|
|
344
|
+
colldict = {coll: {kk: vv for kk, vv in coll_settings.items()
|
|
345
|
+
if kk != 'family' or vv is not None}
|
|
346
|
+
for coll, coll_settings in colldict.items()}
|
|
347
|
+
# Remove None gaps and stages if the collimator is assigned a family (they will be set in _parse_dict)
|
|
348
|
+
colldict = {coll: {kk: vv for kk, vv in coll_settings.items()
|
|
349
|
+
if kk != 'gap' or vv is not None or 'family' not in coll_settings}
|
|
350
|
+
for coll, coll_settings in colldict.items()}
|
|
351
|
+
colldict = {coll: {kk: vv for kk, vv in coll_settings.items()
|
|
352
|
+
if kk != 'stage' or vv is not None or 'family' not in coll_settings}
|
|
353
|
+
for coll, coll_settings in colldict.items()}
|
|
354
|
+
|
|
355
|
+
return cls.from_dict({'collimators': colldict, 'families': famdct}, \
|
|
256
356
|
ignore_crystals=ignore_crystals, **kwargs)
|
|
257
357
|
|
|
358
|
+
def to_pandas(self):
|
|
359
|
+
return pd.DataFrame(self._collimator_dict).transpose()
|
|
258
360
|
|
|
259
|
-
def
|
|
361
|
+
def to_yaml(self, out, lhc_style=True):
|
|
260
362
|
"""
|
|
261
363
|
Writes a colldb in memory to disk in the yaml format.
|
|
262
364
|
|
|
@@ -286,18 +388,18 @@ class CollimatorDatabase:
|
|
|
286
388
|
formatted_key = f'{key}:'.ljust(key_width)
|
|
287
389
|
#formatted_values = formatted_values.ljust(key_width)
|
|
288
390
|
return f"{spacing}{formatted_key} {{ {formatted_values} }}\n"
|
|
289
|
-
|
|
391
|
+
|
|
290
392
|
def _print_values(keys, dct, file, spacing='', mapping=False):
|
|
291
393
|
# Writes formatted dictionary entries to a file
|
|
292
394
|
for key in keys:
|
|
293
395
|
file.write(_format_dict_entry(key, dct[key], spacing=spacing, mapping=mapping))
|
|
294
|
-
|
|
396
|
+
|
|
295
397
|
def _print_colls(colls, dcts, beam, file):
|
|
296
398
|
# Filters and formats collimator data, then writes to a file
|
|
297
399
|
coll_items_to_print = ['<<','gap','angle','material','active','length','side']
|
|
298
400
|
file.write(f' {beam}:\n')
|
|
299
401
|
for coll in colls:
|
|
300
|
-
coll_dict = dcts.
|
|
402
|
+
coll_dict = dcts.to_pandas().transpose().to_dict()[coll]
|
|
301
403
|
fam = coll_dict['family']
|
|
302
404
|
fam_keys = []
|
|
303
405
|
if fam is not None:
|
|
@@ -305,19 +407,19 @@ class CollimatorDatabase:
|
|
|
305
407
|
coll_dict = {**{'<<': '*'+fam}, **coll_dict}
|
|
306
408
|
temp_items_to_print = []
|
|
307
409
|
if coll_dict['crystal'] and str(coll_dict['crystal'])!='nan':
|
|
308
|
-
temp_items_to_print = ['bending_radius','
|
|
309
|
-
if coll_dict['angle_L'] == coll_dict['angle_R']:
|
|
310
|
-
|
|
311
|
-
else:
|
|
312
|
-
|
|
313
|
-
if coll_dict['gap_L'] == coll_dict['gap_R']:
|
|
314
|
-
|
|
315
|
-
elif coll_dict['gap_L'] is None and coll_dict['gap_R'] is not None:
|
|
316
|
-
|
|
317
|
-
elif coll_dict['gap_L'] is not None and coll_dict['gap_R'] is None:
|
|
318
|
-
|
|
319
|
-
else:
|
|
320
|
-
|
|
410
|
+
temp_items_to_print = ['bending_radius','width','height','miscut','crystal']
|
|
411
|
+
# if 'angle_L' in coll_dict and coll_dict['angle_L'] == coll_dict['angle_R']:
|
|
412
|
+
# coll_dict.update({'angle': coll_dict['angle_L']})
|
|
413
|
+
# else:
|
|
414
|
+
# temp_items_to_print = temp_items_to_print + ['angle_L','angle_R']
|
|
415
|
+
# if coll_dict['gap_L'] == coll_dict['gap_R']:
|
|
416
|
+
# coll_dict.update({'gap': coll_dict['gap_L']})
|
|
417
|
+
# elif coll_dict['gap_L'] is None and coll_dict['gap_R'] is not None:
|
|
418
|
+
# coll_dict.update({'gap': coll_dict['gap_R']})
|
|
419
|
+
# elif coll_dict['gap_L'] is not None and coll_dict['gap_R'] is None:
|
|
420
|
+
# coll_dict.update({'gap': coll_dict['gap_L']})
|
|
421
|
+
# else:
|
|
422
|
+
# temp_items_to_print = temp_items_to_print + ['gap_L','gap_R']
|
|
321
423
|
value = {}
|
|
322
424
|
overwritten_keys = coll_dict['overwritten_keys']
|
|
323
425
|
for key, val in coll_dict.items():
|
|
@@ -326,8 +428,7 @@ class CollimatorDatabase:
|
|
|
326
428
|
if (key in coll_items_to_print+temp_items_to_print) and (key not in (set(fam_keys)-set(overwritten_keys))) and (val != 'both'):
|
|
327
429
|
value.update({key: val})
|
|
328
430
|
file.write(_format_dict_entry(coll, value, spacing=' '))
|
|
329
|
-
file.write('\n')
|
|
330
|
-
|
|
431
|
+
file.write('\n')
|
|
331
432
|
|
|
332
433
|
LHC_families = ['tcp3', 'tcsg3', 'tcsm3', 'tcla3', 'tcp7', 'tcsg7', 'tcsm7', 'tcla7', 'tcli', 'tdi', 'tcdq', 'tcstcdq', 'tcth1', 'tcth2', 'tcth5', 'tcth8', 'tctv1', 'tctv2', 'tctv5', 'tctv8', 'tclp', 'tcxrp', 'tcryo', 'tcl4', 'tcl5', 'tcl6', 'tct15', 'tct2', 'tct8', 'tcsp', 'tcld']
|
|
333
434
|
with open(f'{out}.yaml', 'w') as file:
|
|
@@ -376,15 +477,15 @@ class CollimatorDatabase:
|
|
|
376
477
|
_print_values(self._family_dict.keys(), self._family_dict, file, spacing=' - &', mapping=True)
|
|
377
478
|
|
|
378
479
|
# Emittance section
|
|
379
|
-
ex = self.
|
|
380
|
-
ey = self.
|
|
480
|
+
ex = self.nemitt_x
|
|
481
|
+
ey = self.nemitt_y
|
|
381
482
|
file.write(f'\nemittance:\n x: {ex}\n y: {ey}\n')
|
|
382
483
|
|
|
383
484
|
# Collimators section
|
|
384
485
|
file.write('\ncollimators:\n')
|
|
385
486
|
b1_colls, b2_colls, bx_colls = [], [], []
|
|
386
|
-
for coll in self.
|
|
387
|
-
if coll == 'tclia.4r2' or coll == 'tclia.4l8':
|
|
487
|
+
for coll in self.to_pandas().index:
|
|
488
|
+
if coll == 'tclia.4r2' or coll == 'tclia.4l8': # TODO: hardcoded!!!
|
|
388
489
|
b1_colls.append(coll)
|
|
389
490
|
b2_colls.append(coll)
|
|
390
491
|
elif coll[-2:] == 'b1':
|
|
@@ -393,7 +494,7 @@ class CollimatorDatabase:
|
|
|
393
494
|
b2_colls.append(coll)
|
|
394
495
|
else:
|
|
395
496
|
bx_colls.append(coll)
|
|
396
|
-
|
|
497
|
+
|
|
397
498
|
# Handle special cases for collimators
|
|
398
499
|
if (('tclia.4r2' in b1_colls) or ('tclia.4l8' in b1_colls)) and (len(b1_colls) <= 2):
|
|
399
500
|
b1_colls = []
|
|
@@ -410,701 +511,129 @@ class CollimatorDatabase:
|
|
|
410
511
|
print('WARNING -- some collimators could not be assigned to b1 or b2. Tracking might not work with those collimators. Please manually change the output file if necessary.')
|
|
411
512
|
|
|
412
513
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
# is already taken care of)
|
|
472
|
-
if not _yaml_merged:
|
|
473
|
-
overwritten_keys = [key.lower() for key in settings.keys() if key in fam[thisfam]]
|
|
474
|
-
if len(overwritten_keys) > 0:
|
|
475
|
-
settings['overwritten_keys'] = overwritten_keys
|
|
476
|
-
|
|
477
|
-
# Load family settings, potentially overwriting settings for this collimator
|
|
478
|
-
settings = {**fam[thisfam], **settings}
|
|
479
|
-
|
|
480
|
-
else:
|
|
481
|
-
settings['family'] = None
|
|
482
|
-
coll[thiscoll] = settings
|
|
483
|
-
|
|
484
|
-
# Save list of crystals
|
|
485
|
-
if 'crystal' in settings:
|
|
486
|
-
if settings['crystal'] != 0.0:
|
|
487
|
-
crystals += [thiscoll]
|
|
488
|
-
else:
|
|
489
|
-
settings['crystal'] = None
|
|
490
|
-
|
|
491
|
-
# Remove crystals from colldb
|
|
492
|
-
if ignore_crystals:
|
|
493
|
-
for thiscoll in crystals:
|
|
494
|
-
del coll[thiscoll]
|
|
495
|
-
|
|
496
|
-
# Check that all collimators have gap settings
|
|
497
|
-
if not np.all(['gap' in val.keys() or 'opening' in val.keys() for val in coll.values()]):
|
|
498
|
-
raise ValueError("Ill-defined CollimatorDatabase: Not all collimators have a gap or "
|
|
499
|
-
+ "opening setting, (or the keys / structure of the dictionary is wrong)!")
|
|
500
|
-
|
|
501
|
-
# Update collimators with default values for missing keys
|
|
502
|
-
for collimator in coll.values():
|
|
503
|
-
# Change all values to lower case
|
|
504
|
-
for key, val in collimator.items():
|
|
505
|
-
collimator[key] = val.lower() if isinstance(val, str) else val
|
|
506
|
-
if 'length' in collimator.keys():
|
|
507
|
-
collimator['active_length'] = collimator.pop('length')
|
|
508
|
-
if 'gap' in collimator.keys():
|
|
509
|
-
if collimator['gap'] is not None and collimator['gap'] > 900:
|
|
510
|
-
collimator['gap'] = None
|
|
511
|
-
if 'side' in collimator.keys() and collimator['side'] == 'left':
|
|
512
|
-
collimator['gap_L'] = collimator.pop('gap')
|
|
513
|
-
collimator['gap_R'] = None
|
|
514
|
-
elif 'side' in collimator.keys() and collimator['side'] == 'right':
|
|
515
|
-
collimator['gap_L'] = None
|
|
516
|
-
collimator['gap_R'] = collimator.pop('gap')
|
|
517
|
-
else:
|
|
518
|
-
collimator['gap_L'] = collimator['gap']
|
|
519
|
-
collimator['gap_R'] = collimator.pop('gap')
|
|
520
|
-
if 'angle' in collimator.keys():
|
|
521
|
-
collimator['angle_L'] = collimator['angle']
|
|
522
|
-
collimator['angle_R'] = collimator.pop('angle')
|
|
523
|
-
_initialise_None(collimator)
|
|
524
|
-
|
|
525
|
-
self._collimator_dict = coll
|
|
526
|
-
self._family_dict = fam
|
|
527
|
-
self._colldb = pd.DataFrame(coll).transpose()
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
@property
|
|
531
|
-
def name(self):
|
|
532
|
-
return self._colldb.index.values
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
# TODO: - VALIDATION OF TYPES (e.g. material, stage, align, ..)
|
|
536
|
-
# - IMPLEMENTATION OF TILT
|
|
537
|
-
# - CRYSTAL PROPERTIES: only valid if crystal == True (add mask to _set_property?)
|
|
538
|
-
# make second dataframe for crystals
|
|
539
|
-
# - show as __repr__
|
|
540
|
-
|
|
541
|
-
# The CollimatorDatabase class has the following fields (those marked
|
|
542
|
-
# with an * are set automatically and cannot be overwritten):
|
|
543
|
-
# - name
|
|
544
|
-
# - gap
|
|
545
|
-
# - jaw *
|
|
546
|
-
# - beam_size *
|
|
547
|
-
# - s_center *
|
|
548
|
-
# - angle
|
|
549
|
-
# - material
|
|
550
|
-
# - offset
|
|
551
|
-
# - tilt
|
|
552
|
-
# - stage
|
|
553
|
-
# - side
|
|
554
|
-
# - active_length
|
|
555
|
-
# - inactive_front
|
|
556
|
-
# - inactive_back
|
|
557
|
-
# - total_length *
|
|
558
|
-
# - collimator_type *
|
|
559
|
-
# - betx
|
|
560
|
-
# - bety
|
|
561
|
-
# - x
|
|
562
|
-
# - px
|
|
563
|
-
# - y
|
|
564
|
-
# - py
|
|
565
|
-
# - gamma_rel
|
|
566
|
-
# - emit
|
|
567
|
-
|
|
568
|
-
@property
|
|
569
|
-
def angle(self):
|
|
570
|
-
# angles = np.array([self._colldb.angle_L.values,self._colldb.angle_R.values])
|
|
571
|
-
# return pd.Series([ L if L == R else [L,R] for L, R in angles.T ], index=self._colldb.index, dtype=object)
|
|
572
|
-
return self._colldb['angle_L']
|
|
573
|
-
|
|
574
|
-
@angle.setter
|
|
575
|
-
def angle(self, angle):
|
|
576
|
-
self._set_property_LR('angle', angle)
|
|
577
|
-
self._compute_jaws()
|
|
578
|
-
|
|
579
|
-
@property
|
|
580
|
-
def material(self):
|
|
581
|
-
return self._colldb['material']
|
|
582
|
-
|
|
583
|
-
@material.setter
|
|
584
|
-
def material(self, material):
|
|
585
|
-
self._set_property('material', material)
|
|
586
|
-
|
|
587
|
-
@property
|
|
588
|
-
def offset(self):
|
|
589
|
-
return self._colldb['offset']
|
|
590
|
-
|
|
591
|
-
@offset.setter
|
|
592
|
-
def offset(self, offset):
|
|
593
|
-
self._set_property('offset', offset, single_default_allowed=True)
|
|
594
|
-
self._compute_jaws()
|
|
595
|
-
|
|
596
|
-
@property
|
|
597
|
-
def tilt(self):
|
|
598
|
-
tilts = np.array([self._colldb.tilt_L.values,self._colldb.tilt_R.values])
|
|
599
|
-
return pd.Series([ L if L == R else [L,R] for L, R in tilts.T ], index=self._colldb.index, dtype=object)
|
|
600
|
-
|
|
601
|
-
@tilt.setter
|
|
602
|
-
def tilt(self, tilts):
|
|
603
|
-
self._set_property_LR('tilt', tilts)
|
|
604
|
-
self._compute_jaws()
|
|
605
|
-
|
|
606
|
-
@property
|
|
607
|
-
def stage(self):
|
|
608
|
-
return self._colldb['stage']
|
|
609
|
-
|
|
610
|
-
@stage.setter
|
|
611
|
-
def stage(self, stage):
|
|
612
|
-
self._set_property('stage', stage)
|
|
613
|
-
|
|
614
|
-
@property
|
|
615
|
-
def parking(self):
|
|
616
|
-
return self._colldb['parking']
|
|
617
|
-
|
|
618
|
-
@parking.setter
|
|
619
|
-
def parking(self, parking):
|
|
620
|
-
self._set_property('parking', parking, single_default_allowed=True)
|
|
621
|
-
self._compute_jaws()
|
|
622
|
-
|
|
623
|
-
@property
|
|
624
|
-
def active(self):
|
|
625
|
-
return self._colldb['active']
|
|
626
|
-
|
|
627
|
-
@active.setter
|
|
628
|
-
def active(self, active):
|
|
629
|
-
self._set_property('active', active, single_default_allowed=True)
|
|
630
|
-
|
|
631
|
-
# @property
|
|
632
|
-
# def crystal(self):
|
|
633
|
-
# return self._colldb['crystal']
|
|
634
|
-
|
|
635
|
-
# @crystal.setter
|
|
636
|
-
# def crystal(self, crystal):
|
|
637
|
-
# self._set_property('crystal', crystal)
|
|
638
|
-
|
|
639
|
-
# @property
|
|
640
|
-
# def bend(self):
|
|
641
|
-
# return self._colldb['bend']
|
|
642
|
-
|
|
643
|
-
# @bend.setter
|
|
644
|
-
# def bend(self, bend):
|
|
645
|
-
# self._set_property('bend', bend)
|
|
646
|
-
|
|
647
|
-
# @property
|
|
648
|
-
# def xdim(self):
|
|
649
|
-
# return self._colldb['xdim']
|
|
650
|
-
|
|
651
|
-
# @xdim.setter
|
|
652
|
-
# def xdim(self, xdim):
|
|
653
|
-
# self._set_property('xdim', xdim)
|
|
654
|
-
|
|
655
|
-
# @property
|
|
656
|
-
# def ydim(self):
|
|
657
|
-
# return self._colldb['ydim']
|
|
658
|
-
|
|
659
|
-
# @ydim.setter
|
|
660
|
-
# def ydim(self, ydim):
|
|
661
|
-
# self._set_property('ydim', ydim)
|
|
662
|
-
|
|
663
|
-
# @property
|
|
664
|
-
# def miscut(self):
|
|
665
|
-
# return self._colldb['miscut']
|
|
666
|
-
|
|
667
|
-
# @miscut.setter
|
|
668
|
-
# def miscut(self, miscut):
|
|
669
|
-
# self._set_property('miscut', miscut)
|
|
670
|
-
|
|
671
|
-
# @property
|
|
672
|
-
# def thick(self):
|
|
673
|
-
# return self._colldb['thick']
|
|
674
|
-
|
|
675
|
-
# @thick.setter
|
|
676
|
-
# def thick(self, thick):
|
|
677
|
-
# self._set_property('thick', thick)
|
|
678
|
-
|
|
679
|
-
@property
|
|
680
|
-
def s_center(self):
|
|
681
|
-
return self._colldb['s_center']
|
|
682
|
-
|
|
683
|
-
@property
|
|
684
|
-
def collimator_type(self):
|
|
685
|
-
return self._colldb['collimator_type']
|
|
686
|
-
|
|
687
|
-
@property
|
|
688
|
-
def active_length(self):
|
|
689
|
-
return self._colldb['active_length']
|
|
690
|
-
|
|
691
|
-
@active_length.setter
|
|
692
|
-
def active_length(self, length):
|
|
693
|
-
self._set_property('active_length', length)
|
|
694
|
-
self.align_to = {}
|
|
695
|
-
|
|
696
|
-
@property
|
|
697
|
-
def inactive_front(self):
|
|
698
|
-
return self._colldb['inactive_front']
|
|
699
|
-
|
|
700
|
-
@inactive_front.setter
|
|
701
|
-
def inactive_front(self, length):
|
|
702
|
-
self._set_property('inactive_front', length)
|
|
703
|
-
|
|
704
|
-
@property
|
|
705
|
-
def inactive_back(self):
|
|
706
|
-
return self._colldb['inactive_back']
|
|
707
|
-
|
|
708
|
-
@inactive_back.setter
|
|
709
|
-
def inactive_back(self, length):
|
|
710
|
-
self._set_property('inactive_back', length)
|
|
711
|
-
|
|
712
|
-
@property
|
|
713
|
-
def total_length(self):
|
|
714
|
-
return self._colldb['active_length'] + self._colldb['inactive_front'] + self._colldb['inactive_back']
|
|
715
|
-
|
|
716
|
-
@property
|
|
717
|
-
def gap(self):
|
|
718
|
-
gaps = np.array([self._colldb.gap_L.values,self._colldb.gap_R.values])
|
|
719
|
-
return pd.Series([ L if L == R else [L,R] for L, R in gaps.T ], index=self._colldb.index, dtype=object)
|
|
720
|
-
|
|
721
|
-
@gap.setter
|
|
722
|
-
def gap(self, gaps):
|
|
723
|
-
df = self._colldb
|
|
724
|
-
correct_format = False
|
|
725
|
-
# The variable gaps is a Series or a list
|
|
726
|
-
if isinstance(gaps, pd.Series) or isinstance(gaps, list) or isinstance(gaps, np.ndarray):
|
|
727
|
-
correct_format = True
|
|
728
|
-
if len(gaps) != len(self.name):
|
|
729
|
-
raise ValueError("The variable 'gaps' has a different length than the number "
|
|
730
|
-
+ "of collimators in the CollimatorDatabase. Use a dictionary instead.")
|
|
731
|
-
# Some of the gaps are list (e.g. two different values for both gaps): loop over gaps as dict
|
|
732
|
-
if any(hasattr(gap, '__iter__') for gap in gaps):
|
|
733
|
-
gaps = dict(zip(self.name, gaps))
|
|
734
|
-
# All gaps are single values: use pandas-style assignment
|
|
514
|
+
# ====================================
|
|
515
|
+
# ====== Installing collimators ======
|
|
516
|
+
# ====================================
|
|
517
|
+
|
|
518
|
+
def _get_names_from_line(self, line, names, families):
|
|
519
|
+
if names is None and families is None:
|
|
520
|
+
names = self.collimator_names
|
|
521
|
+
elif names is None:
|
|
522
|
+
names = self.get_collimators_from_family(families)
|
|
523
|
+
elif families is not None:
|
|
524
|
+
names.append(self.get_collimators_from_family(families))
|
|
525
|
+
return list(set(names)) # Remove duplicates
|
|
526
|
+
|
|
527
|
+
def _check_installed(self, line, name, collimator_class):
|
|
528
|
+
# Check that collimator is not installed as different type
|
|
529
|
+
# TODO: automatically replace collimator type and print warning
|
|
530
|
+
if isinstance(line[name], _all_collimator_classes):
|
|
531
|
+
raise ValueError(f"Trying to install {name} as {collimator_class.__name__}, "
|
|
532
|
+
+ f"but it is already installed as {line[name].__class__.__name__}!\n"
|
|
533
|
+
+ f"Please reconstruct the line.")
|
|
534
|
+
# TODO: only allow Marker elements, no Drifts!!
|
|
535
|
+
# How to do this with importing a line for MAD-X or SixTrack...?
|
|
536
|
+
# Maybe we want a DriftCollimator type in Xtrack as a general placeholder
|
|
537
|
+
elif not isinstance(line[name], (xt.Marker, xt.Drift)):
|
|
538
|
+
raise ValueError(f"Trying to install {name} as {collimator_class.__name__}, "
|
|
539
|
+
+ f"but the line element to replace is not an xtrack.Marker "
|
|
540
|
+
+ f"(or xtrack.Drift)!\nPlease check the name, or correct the "
|
|
541
|
+
+ f"element.")
|
|
542
|
+
|
|
543
|
+
def _create_collimator(self, line, collimator_class, name, **kwargs):
|
|
544
|
+
assert issubclass(collimator_class, BaseCollimator)
|
|
545
|
+
self._check_installed(line, name, collimator_class)
|
|
546
|
+
if kwargs.pop('verbose', False):
|
|
547
|
+
print(f"Installing {name:20} as {collimator_class.__name__}")
|
|
548
|
+
el = collimator_class(gap=self[name]['gap'], angle=self[name]['angle'],
|
|
549
|
+
length=self[name]['length'], side=self[name]['side'],
|
|
550
|
+
_tracking=False, **kwargs)
|
|
551
|
+
el.emittance = [self.nemitt_x, self.nemitt_y]
|
|
552
|
+
self._elements[name] = el
|
|
553
|
+
|
|
554
|
+
def _create_crystal(self, line, crystal_class, name, **kwargs):
|
|
555
|
+
assert issubclass(crystal_class, BaseCrystal)
|
|
556
|
+
self._check_installed(line, name, crystal_class)
|
|
557
|
+
if kwargs.pop('verbose', False):
|
|
558
|
+
print(f"Installing {name:20} as {crystal_class.__name__}")
|
|
559
|
+
el = crystal_class(gap=self[name]['gap'], angle=self[name]['angle'],
|
|
560
|
+
length=self[name]['length'], side=self[name]['side'],
|
|
561
|
+
bending_radius=self[name]['bending_radius'],
|
|
562
|
+
width=self[name]['width'], height=self[name]['height'],
|
|
563
|
+
_tracking=False, **kwargs)
|
|
564
|
+
el.emittance = [self.nemitt_x, self.nemitt_y]
|
|
565
|
+
self._elements[name] = el
|
|
566
|
+
|
|
567
|
+
def install_black_absorbers(self, line, *, names=None, families=None, verbose=False, need_apertures=True):
|
|
568
|
+
names = self._get_names_from_line(line, names, families)
|
|
569
|
+
for name in names:
|
|
570
|
+
if self[name]['bending_radius'] is None:
|
|
571
|
+
self._create_collimator(line, BlackAbsorber, name, verbose=verbose)
|
|
735
572
|
else:
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
correct_format = True
|
|
748
|
-
for name, gap in gaps.items():
|
|
749
|
-
if name not in self.name:
|
|
750
|
-
raise ValueError(f"Collimator {name} not found in CollimatorDatabase!")
|
|
751
|
-
side = df.side[name]
|
|
752
|
-
if hasattr(gap, '__iter__'):
|
|
753
|
-
if isinstance(gap, str):
|
|
754
|
-
raise ValueError("The gap setting has to be a number!")
|
|
755
|
-
elif len(gap) == 2:
|
|
756
|
-
gap_L = gap[0]
|
|
757
|
-
gap_R = gap[1]
|
|
758
|
-
if side != 'both':
|
|
759
|
-
if side == 'left' and gap_R is not None:
|
|
760
|
-
print(f"Warning: collimator {name} is left-sided but a finite right gap is specified. "
|
|
761
|
-
+ "Verify that this is what you want.")
|
|
762
|
-
elif side == 'right' and gap_L is not None:
|
|
763
|
-
print(f"Warning: collimator {name} is right-sided but a finite left gap is specified. "
|
|
764
|
-
+ "Verify that this is what you want.")
|
|
765
|
-
elif len(gap) == 1:
|
|
766
|
-
gap_L = gap[0] if side in ['both','left'] else None
|
|
767
|
-
gap_R = gap[0] if side in ['both','right'] else None
|
|
768
|
-
else:
|
|
769
|
-
raise ValueError("The gap setting must have one or two values (for the left and the right jaw)!")
|
|
770
|
-
else:
|
|
771
|
-
gap_L = gap if side in ['both','left'] else None
|
|
772
|
-
gap_R = gap if side in ['both','right'] else None
|
|
773
|
-
gap_L = None if (gap_L is not None and gap_L >= 900) else gap_L
|
|
774
|
-
gap_R = None if (gap_R is not None and gap_R >= 900) else gap_R
|
|
775
|
-
df.loc[name, 'gap_L'] = gap_L
|
|
776
|
-
df.loc[name, 'gap_R'] = gap_R
|
|
777
|
-
|
|
778
|
-
if not correct_format:
|
|
779
|
-
raise ValueError("Variable 'gaps' needs to be a pandas Series, dict, numpy array, or list!")
|
|
780
|
-
|
|
781
|
-
df.gap_L = df.gap_L.astype('object', copy=False)
|
|
782
|
-
df.gap_R = df.gap_R.astype('object', copy=False)
|
|
783
|
-
self._compute_jaws()
|
|
784
|
-
|
|
785
|
-
@property
|
|
786
|
-
def jaw(self):
|
|
787
|
-
jaws = list(np.array([
|
|
788
|
-
self._colldb.jaw_LU.values,
|
|
789
|
-
self._colldb.jaw_RU.values,
|
|
790
|
-
self._colldb.jaw_LD.values,
|
|
791
|
-
self._colldb.jaw_RD.values
|
|
792
|
-
]).T)
|
|
793
|
-
# Need special treatment if there are None's
|
|
794
|
-
def flip(jaw):
|
|
795
|
-
return None if jaw is None else -jaw
|
|
796
|
-
for i, jaw in enumerate(jaws):
|
|
797
|
-
# All 4 jaw points are the same
|
|
798
|
-
if jaw[0] == flip(jaw[1]) == jaw[2] == flip(jaw[3]):
|
|
799
|
-
jaws[i] = jaw[0]
|
|
800
|
-
# Upstream and downstream jaws are the same
|
|
801
|
-
# (all cases except angular alignment and/or tilt)
|
|
802
|
-
elif jaw[0] == jaw[2] and jaw[1] == jaw[3]:
|
|
803
|
-
jaws[i] = [ jaw[0], jaw[1] ]
|
|
573
|
+
self._create_crystal(line, BlackCrystal, name, verbose=verbose)
|
|
574
|
+
elements = [self._elements[name] for name in names]
|
|
575
|
+
install_elements(line, names, elements, need_apertures=need_apertures)
|
|
576
|
+
|
|
577
|
+
def install_everest_collimators(self, line, *, names=None, families=None, verbose=False, need_apertures=True):
|
|
578
|
+
names = self._get_names_from_line(line, names, families)
|
|
579
|
+
for name in names:
|
|
580
|
+
mat = SixTrack_to_xcoll(self[name]['material'])
|
|
581
|
+
if self[name]['bending_radius'] is None:
|
|
582
|
+
self._create_collimator(line, EverestCollimator, name, material=mat[0],
|
|
583
|
+
verbose=verbose)
|
|
804
584
|
else:
|
|
805
|
-
|
|
806
|
-
|
|
585
|
+
self._create_crystal(line, EverestCrystal, name, material=mat[1],
|
|
586
|
+
lattice=self[name]['crystal'], verbose=verbose,
|
|
587
|
+
miscut=self[name]['miscut'])
|
|
588
|
+
elements = [self._elements[name] for name in names]
|
|
589
|
+
install_elements(line, names, elements, need_apertures=need_apertures)
|
|
807
590
|
|
|
808
|
-
@property
|
|
809
|
-
def side(self):
|
|
810
|
-
return self._colldb.side
|
|
811
591
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
self.gap = self.gap
|
|
592
|
+
# ==================================
|
|
593
|
+
# ====== Accessing attributes ======
|
|
594
|
+
# ==================================
|
|
816
595
|
|
|
817
596
|
@property
|
|
818
|
-
def
|
|
819
|
-
return
|
|
820
|
-
|
|
821
|
-
@gamma_rel.setter
|
|
822
|
-
def gamma_rel(self, gamma_rel):
|
|
823
|
-
self._beta_gamma_rel = np.sqrt(gamma_rel**2-1)
|
|
824
|
-
self._compute_jaws()
|
|
597
|
+
def collimator_names(self):
|
|
598
|
+
return list(self._collimator_dict.keys())
|
|
825
599
|
|
|
826
600
|
@property
|
|
827
|
-
def
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
if isinstance(emit, str):
|
|
834
|
-
raise ValueError(f"The 'emit' setting has to be a number!")
|
|
835
|
-
elif len(emit) == 2:
|
|
836
|
-
self._emitx = emit[0]
|
|
837
|
-
self._emity = emit[1]
|
|
838
|
-
elif len(emit) == 1:
|
|
839
|
-
self._emitx = emit[0]
|
|
840
|
-
self._emity = emit[0]
|
|
601
|
+
def collimator_families(self):
|
|
602
|
+
families = {fam: [] for fam in self._family_dict.keys()}
|
|
603
|
+
families["no family"] = []
|
|
604
|
+
for name in self.collimator_names:
|
|
605
|
+
if 'family' not in self[name] or self[name]['family'].lower() == 'unknown':
|
|
606
|
+
families["no family"].append(name)
|
|
841
607
|
else:
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
self._set_property('align_to', align, single_default_allowed=True, limit_to=['front', 'center', 'back', 'angular'])
|
|
855
|
-
if np.any(self.align_to == 'maximum'):
|
|
856
|
-
raise NotImplementedError
|
|
857
|
-
s_front = self.s_center - self.active_length/2
|
|
858
|
-
s_center = self.s_center
|
|
859
|
-
s_back = self.s_center + self.active_length/2
|
|
860
|
-
mask = self.align_to == 'front'
|
|
861
|
-
self._colldb.loc[mask,'s_align_front'] = s_front[mask]
|
|
862
|
-
self._colldb.loc[mask,'s_align_back'] = s_front[mask]
|
|
863
|
-
mask = self.align_to == 'center'
|
|
864
|
-
self._colldb.loc[mask,'s_align_front'] = s_center[mask]
|
|
865
|
-
self._colldb.loc[mask,'s_align_back'] = s_center[mask]
|
|
866
|
-
mask = self.align_to == 'back'
|
|
867
|
-
self._colldb.loc[mask,'s_align_front'] = s_back[mask]
|
|
868
|
-
self._colldb.loc[mask,'s_align_back'] = s_back[mask]
|
|
869
|
-
mask = self.align_to == 'angular'
|
|
870
|
-
self._colldb.loc[mask,'s_align_front'] = s_front[mask]
|
|
871
|
-
self._colldb.loc[mask,'s_align_back'] = s_back[mask]
|
|
872
|
-
self._compute_jaws()
|
|
873
|
-
|
|
874
|
-
# TODO: when does this need to be unset?
|
|
875
|
-
@property
|
|
876
|
-
def _optics_is_ready(self):
|
|
877
|
-
pos = set(self._colldb.s_align_front.values) | set(self._colldb.s_align_back.values)
|
|
878
|
-
return np.all([s in self._optics.index for s in pos]) and self._beta_gamma_rel is not None
|
|
879
|
-
|
|
880
|
-
@property
|
|
881
|
-
def betx(self):
|
|
882
|
-
vals = np.array([
|
|
883
|
-
[ self._optics.loc[s,'betx'] if s in self._optics.index else None for s in self._colldb.s_align_front.values ],
|
|
884
|
-
[ self._optics.loc[s,'betx'] if s in self._optics.index else None for s in self._colldb.s_align_back.values ]
|
|
885
|
-
])
|
|
886
|
-
return pd.Series([ F if F == B else [F,B] for F,B in vals.T ], index=self._colldb.index, dtype=object)
|
|
887
|
-
|
|
888
|
-
@property
|
|
889
|
-
def bety(self):
|
|
890
|
-
vals = np.array([
|
|
891
|
-
[ self._optics.loc[s,'bety'] if s in self._optics.index else None for s in self._colldb.s_align_front.values ],
|
|
892
|
-
[ self._optics.loc[s,'bety'] if s in self._optics.index else None for s in self._colldb.s_align_back.values ]
|
|
893
|
-
])
|
|
894
|
-
return pd.Series([ F if F == B else [F,B] for F,B in vals.T ], index=self._colldb.index, dtype=object)
|
|
895
|
-
|
|
896
|
-
@property
|
|
897
|
-
def alfx(self):
|
|
898
|
-
vals = np.array([
|
|
899
|
-
[ self._optics.loc[s,'alfx'] if s in self._optics.index else None for s in self._colldb.s_align_front.values ],
|
|
900
|
-
[ self._optics.loc[s,'alfx'] if s in self._optics.index else None for s in self._colldb.s_align_back.values ]
|
|
901
|
-
])
|
|
902
|
-
return pd.Series([ F if F == B else [F,B] for F,B in vals.T ], index=self._colldb.index, dtype=object)
|
|
903
|
-
|
|
904
|
-
@property
|
|
905
|
-
def alfy(self):
|
|
906
|
-
vals = np.array([
|
|
907
|
-
[ self._optics.loc[s,'alfy'] if s in self._optics.index else None for s in self._colldb.s_align_front.values ],
|
|
908
|
-
[ self._optics.loc[s,'alfy'] if s in self._optics.index else None for s in self._colldb.s_align_back.values ]
|
|
909
|
-
])
|
|
910
|
-
return pd.Series([ F if F == B else [F,B] for F,B in vals.T ], index=self._colldb.index, dtype=object)
|
|
911
|
-
|
|
912
|
-
@property
|
|
913
|
-
def dx(self):
|
|
914
|
-
vals = np.array([
|
|
915
|
-
[ self._optics.loc[s,'dx'] if s in self._optics.index else None for s in self._colldb.s_align_front.values ],
|
|
916
|
-
[ self._optics.loc[s,'dx'] if s in self._optics.index else None for s in self._colldb.s_align_back.values ]
|
|
917
|
-
])
|
|
918
|
-
return pd.Series([ F if F == B else [F,B] for F,B in vals.T ], index=self._colldb.index, dtype=object)
|
|
919
|
-
|
|
920
|
-
@property
|
|
921
|
-
def dy(self):
|
|
922
|
-
vals = np.array([
|
|
923
|
-
[ self._optics.loc[s,'dy'] if s in self._optics.index else None for s in self._colldb.s_align_front.values ],
|
|
924
|
-
[ self._optics.loc[s,'dy'] if s in self._optics.index else None for s in self._colldb.s_align_back.values ]
|
|
925
|
-
])
|
|
926
|
-
return pd.Series([ F if F == B else [F,B] for F,B in vals.T ], index=self._colldb.index, dtype=object)
|
|
927
|
-
|
|
928
|
-
@property
|
|
929
|
-
def x(self):
|
|
930
|
-
vals = np.array([
|
|
931
|
-
[ self._optics.loc[s,'x'] if s in self._optics.index else None for s in self._colldb.s_align_front.values ],
|
|
932
|
-
[ self._optics.loc[s,'x'] if s in self._optics.index else None for s in self._colldb.s_align_back.values ]
|
|
933
|
-
])
|
|
934
|
-
return pd.Series([ F if F == B else [F,B] for F,B in vals.T ], index=self._colldb.index, dtype=object)
|
|
935
|
-
|
|
936
|
-
@property
|
|
937
|
-
def px(self):
|
|
938
|
-
vals = np.array([
|
|
939
|
-
[ self._optics.loc[s,'px'] if s in self._optics.index else None for s in self._colldb.s_align_front.values ],
|
|
940
|
-
[ self._optics.loc[s,'px'] if s in self._optics.index else None for s in self._colldb.s_align_back.values ]
|
|
941
|
-
])
|
|
942
|
-
return pd.Series([ F if F == B else [F,B] for F,B in vals.T ], index=self._colldb.index, dtype=object)
|
|
943
|
-
|
|
944
|
-
@property
|
|
945
|
-
def y(self):
|
|
946
|
-
vals = np.array([
|
|
947
|
-
[ self._optics.loc[s,'y'] if s in self._optics.index else None for s in self._colldb.s_align_front.values ],
|
|
948
|
-
[ self._optics.loc[s,'y'] if s in self._optics.index else None for s in self._colldb.s_align_back.values ]
|
|
949
|
-
])
|
|
950
|
-
return pd.Series([ F if F == B else [F,B] for F,B in vals.T ], index=self._colldb.index, dtype=object)
|
|
608
|
+
families[self[name]['family']].append(name)
|
|
609
|
+
return families
|
|
610
|
+
|
|
611
|
+
def get_collimators_from_family(self, family):
|
|
612
|
+
if not hasattr(family, '__iter__') and not isinstance(family, str):
|
|
613
|
+
family = [family]
|
|
614
|
+
result = []
|
|
615
|
+
for fam in family:
|
|
616
|
+
if fam not in self.collimator_families:
|
|
617
|
+
raise ValueError(f"Family '{fam}' not found in CollimatorDatabase!")
|
|
618
|
+
result += self.collimator_families[fam]
|
|
619
|
+
return result
|
|
951
620
|
|
|
952
621
|
@property
|
|
953
|
-
def
|
|
954
|
-
|
|
955
|
-
[ self._optics.loc[s,'py'] if s in self._optics.index else None for s in self._colldb.s_align_front.values ],
|
|
956
|
-
[ self._optics.loc[s,'py'] if s in self._optics.index else None for s in self._colldb.s_align_back.values ]
|
|
957
|
-
])
|
|
958
|
-
return pd.Series([ F if F == B else [F,B] for F,B in vals.T ], index=self._colldb.index, dtype=object)
|
|
622
|
+
def properties(self):
|
|
623
|
+
return {attr for d in self._collimator_dict.values() for attr in d.keys()}
|
|
959
624
|
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
return pd.Series([ F if F == B else [F,B] for F, B in beam_size.T ], index=self._colldb.index, dtype=object)
|
|
625
|
+
def __getattr__(self, attr):
|
|
626
|
+
if attr in self.properties:
|
|
627
|
+
# TODO: include families
|
|
628
|
+
return {kk: vv.get(attr, None) for kk, vv in self._collimator_dict.items()}
|
|
965
629
|
else:
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
@property
|
|
969
|
-
def _beam_size_front(self):
|
|
970
|
-
# TODO: curretnly only for angle_L
|
|
971
|
-
df = self._colldb
|
|
972
|
-
opt = self._optics
|
|
973
|
-
betx = opt.loc[df.s_align_front,'betx'].astype(float)
|
|
974
|
-
bety = opt.loc[df.s_align_front,'bety'].astype(float)
|
|
975
|
-
sigmax = np.sqrt(betx*self._emitx/self._beta_gamma_rel)
|
|
976
|
-
sigmay = np.sqrt(bety*self._emity/self._beta_gamma_rel)
|
|
977
|
-
result = np.sqrt(
|
|
978
|
-
(sigmax*np.cos(np.float_(df.angle_L.values)*np.pi/180))**2
|
|
979
|
-
+ (sigmay*np.sin(np.float_(df.angle_L.values)*np.pi/180))**2
|
|
980
|
-
)
|
|
981
|
-
result.index = self._colldb.index
|
|
982
|
-
return result
|
|
630
|
+
raise ValueError(f"Property `{attr}` not present in CollimatorDatabase!")
|
|
983
631
|
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
betx = opt.loc[df.s_align_back,'betx'].astype(float)
|
|
990
|
-
bety = opt.loc[df.s_align_back,'bety'].astype(float)
|
|
991
|
-
sigmax = np.sqrt(betx*self._emitx/self._beta_gamma_rel)
|
|
992
|
-
sigmay = np.sqrt(bety*self._emity/self._beta_gamma_rel)
|
|
993
|
-
result = np.sqrt(
|
|
994
|
-
(sigmax*np.cos(np.float_(df.angle_L.values)*np.pi/180))**2
|
|
995
|
-
+ (sigmay*np.sin(np.float_(df.angle_L.values)*np.pi/180))**2
|
|
996
|
-
)
|
|
997
|
-
result.index = self._colldb.index
|
|
998
|
-
return result
|
|
999
|
-
|
|
1000
|
-
# parking is defined with respect to closed orbit
|
|
1001
|
-
# TODO: tilt
|
|
1002
|
-
# 'upstr' => 'front' en 'downstr' => 'back'
|
|
1003
|
-
def _compute_jaws(self):
|
|
1004
|
-
if self._optics_is_ready:
|
|
1005
|
-
df = self._colldb
|
|
1006
|
-
beam_size_front = self._beam_size_front
|
|
1007
|
-
beam_size_back = self._beam_size_back
|
|
1008
|
-
jaw_LU = df['gap_L']*beam_size_front + self.offset
|
|
1009
|
-
jaw_RU = df['gap_R']*beam_size_front - self.offset
|
|
1010
|
-
jaw_LD = df['gap_L']*beam_size_back + self.offset
|
|
1011
|
-
jaw_RD = df['gap_R']*beam_size_back - self.offset
|
|
1012
|
-
df['jaw_LU'] = df['parking'] if df['gap_L'] is None else np.minimum(jaw_LU,df['parking'])
|
|
1013
|
-
df['jaw_RU'] = -df['parking'] if df['gap_R'] is None else -np.minimum(jaw_RU,df['parking'])
|
|
1014
|
-
df['jaw_LD'] = df['parking'] if df['gap_L'] is None else np.minimum(jaw_LD,df['parking'])
|
|
1015
|
-
df['jaw_RD'] = -df['parking'] if df['gap_R'] is None else -np.minimum(jaw_RD,df['parking'])
|
|
1016
|
-
# align crystals
|
|
1017
|
-
opt = self._optics
|
|
1018
|
-
df['align_angle'] = None
|
|
1019
|
-
cry_mask = [c is not None for c in df.crystal]
|
|
1020
|
-
df_cry = df[cry_mask]
|
|
1021
|
-
if len(df_cry) > 0:
|
|
1022
|
-
alfx = opt.loc[df_cry.s_align_front,'alfx'].astype(float).values
|
|
1023
|
-
alfy = opt.loc[df_cry.s_align_front,'alfy'].astype(float).values
|
|
1024
|
-
betx = opt.loc[df_cry.s_align_front,'betx'].astype(float).values
|
|
1025
|
-
bety = opt.loc[df_cry.s_align_front,'bety'].astype(float).values
|
|
1026
|
-
align_angle_x = -np.sqrt(self._emitx/self._beta_gamma_rel/betx)*alfx
|
|
1027
|
-
align_angle_y = -np.sqrt(self._emity/self._beta_gamma_rel/bety)*alfy
|
|
1028
|
-
align_angle = np.array([x if abs(ang) < 1e-6 else y
|
|
1029
|
-
for x,y,ang in zip(align_angle_x,align_angle_y,df_cry.angle_L.values)])
|
|
1030
|
-
df.loc[cry_mask, 'align_angle'] = align_angle*df_cry['gap_L']
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
# ---------------------------------------
|
|
1034
|
-
# ------ Property setter functions ------
|
|
1035
|
-
# ---------------------------------------
|
|
1036
|
-
|
|
1037
|
-
def _set_property(self, prop, vals, single_default_allowed=False, limit_to=[]):
|
|
1038
|
-
df = self._colldb
|
|
1039
|
-
if not isinstance(limit_to, (list, tuple, set)):
|
|
1040
|
-
limit_to = [limit_to]
|
|
1041
|
-
if isinstance(vals, dict):
|
|
1042
|
-
for name, val in vals.items():
|
|
1043
|
-
if name not in self.name:
|
|
1044
|
-
raise ValueError(f"Collimator {name} not found in CollimatorDatabase!")
|
|
1045
|
-
if limit_to!=[] and val not in limit_to:
|
|
1046
|
-
raise ValueError(f"Cannot set {prop} to {val}. Choose from {limit_to}!")
|
|
1047
|
-
df.loc[name, prop] = val
|
|
1048
|
-
elif isinstance(vals, pd.Series) or isinstance(vals, list) or isinstance(vals, np.ndarray):
|
|
1049
|
-
if len(vals) != len(self.name):
|
|
1050
|
-
raise ValueError(f"The variable '{prop}' has a different length than the number of "
|
|
1051
|
-
+ "collimators in the CollimatorDatabase. Use a dictionary instead.")
|
|
1052
|
-
if limit_to!=[] and np.any([val not in limit_to for val in vals]):
|
|
1053
|
-
raise ValueError(f"Cannot set {prop} to {vals}. Choose from {limit_to}!")
|
|
1054
|
-
df[prop] = vals
|
|
632
|
+
def __getitem__(self, name):
|
|
633
|
+
if name in self._family_dict:
|
|
634
|
+
return self._family_dict[name]
|
|
635
|
+
elif name in self._collimator_dict:
|
|
636
|
+
return self._collimator_dict[name]
|
|
1055
637
|
else:
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
raise ValueError(f"Cannot set {prop} to {vals}. Choose from {limit_to}!")
|
|
1059
|
-
df[prop] = vals
|
|
1060
|
-
else:
|
|
1061
|
-
raise ValueError(f"Variable '{prop}' needs to be a pandas Series, dict, numpy array, or list!")
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
def _set_property_LR(self, prop, vals):
|
|
1065
|
-
df = self._colldb
|
|
1066
|
-
correct_format = False
|
|
1067
|
-
# The variable vals is a Series or a list
|
|
1068
|
-
if isinstance(vals, pd.Series) or isinstance(vals, list) or isinstance(vals, np.ndarray):
|
|
1069
|
-
correct_format = True
|
|
1070
|
-
if len(vals) != len(self.name):
|
|
1071
|
-
raise ValueError(f"The variable '{prop}' has a different length than the number of "
|
|
1072
|
-
+ "collimators in the CollimatorDatabase. Use a dictionary instead.")
|
|
1073
|
-
# Some of the vals are list (e.g. two different values for both gaps): loop over vals as dict
|
|
1074
|
-
if any(hasattr(val, '__iter__') for val in vals):
|
|
1075
|
-
vals = dict(zip(self.name, vals))
|
|
1076
|
-
# All gaps are single values: use pandas-style assignment
|
|
1077
|
-
else:
|
|
1078
|
-
df[prop + "_L"] = vals
|
|
1079
|
-
df[prop + "_R"] = vals
|
|
1080
|
-
|
|
1081
|
-
# The variable vals is a dictionary
|
|
1082
|
-
if isinstance(vals, dict):
|
|
1083
|
-
correct_format = True
|
|
1084
|
-
for name, val in vals.items():
|
|
1085
|
-
if name not in self.name:
|
|
1086
|
-
raise ValueError(f"Collimator {name} not found in CollimatorDatabase!")
|
|
1087
|
-
if hasattr(val, '__iter__'):
|
|
1088
|
-
if isinstance(val, str):
|
|
1089
|
-
raise ValueError(f"The '{prop}' setting has to be a number!")
|
|
1090
|
-
elif len(val) == 2:
|
|
1091
|
-
val_L = val[0]
|
|
1092
|
-
val_R = val[1]
|
|
1093
|
-
elif len(val) == 1:
|
|
1094
|
-
val_L = val[0]
|
|
1095
|
-
val_R = val[0]
|
|
1096
|
-
else:
|
|
1097
|
-
raise ValueError(f"The '{prop}' setting must have one or two values (for the left and the right jaw)!")
|
|
1098
|
-
else:
|
|
1099
|
-
val_L = val
|
|
1100
|
-
val_R = val
|
|
1101
|
-
df.loc[name, prop + "_L"] = val_L
|
|
1102
|
-
df.loc[name, prop + "_R"] = val_R
|
|
1103
|
-
|
|
1104
|
-
if not correct_format:
|
|
1105
|
-
raise ValueError("Variable '{prop}' needs to be a pandas Series, dict, numpy array, or list!")
|
|
1106
|
-
|
|
1107
|
-
df[prop + "_L"] = df[prop + "_L"].astype('object', copy=False)
|
|
1108
|
-
df[prop + "_R"] = df[prop + "_R"].astype('object', copy=False)
|
|
1109
|
-
# Check if collimator active
|
|
1110
|
-
# Check if gap is list (assymetric jaws)
|
|
638
|
+
raise ValueError(f"Family nor collimator `{name}` found in CollimatorDatabase!")
|
|
639
|
+
|