xtrack 0.44.1__tar.gz → 0.46.0__tar.gz

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.
Files changed (139) hide show
  1. {xtrack-0.44.1/xtrack.egg-info → xtrack-0.46.0}/PKG-INFO +1 -1
  2. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/__init__.py +2 -1
  3. xtrack-0.46.0/xtrack/_version.py +1 -0
  4. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/line.py +23 -21
  5. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/mad_loader.py +9 -21
  6. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/match.py +200 -33
  7. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/multisetter/multisetter.py +17 -14
  8. xtrack-0.46.0/xtrack/progress_indicator.py +93 -0
  9. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/slicing.py +2 -6
  10. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/survey.py +1 -3
  11. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/tracker.py +37 -4
  12. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/twiss.py +390 -55
  13. {xtrack-0.44.1 → xtrack-0.46.0/xtrack.egg-info}/PKG-INFO +1 -1
  14. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack.egg-info/SOURCES.txt +1 -0
  15. xtrack-0.44.1/xtrack/_version.py +0 -1
  16. {xtrack-0.44.1 → xtrack-0.46.0}/LICENSE +0 -0
  17. {xtrack-0.44.1 → xtrack-0.46.0}/MANIFEST.in +0 -0
  18. {xtrack-0.44.1 → xtrack-0.46.0}/README.md +0 -0
  19. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/__init__.py +0 -0
  20. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/base_classes.py +0 -0
  21. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/be_beamfields/BB6D.py +0 -0
  22. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/be_beamfields/BB6Ddata.py +0 -0
  23. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/be_beamfields/__init__.py +0 -0
  24. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/be_beamfields/beambeam.py +0 -0
  25. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/be_beamfields/boost.py +0 -0
  26. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/be_beamfields/gaussian_fields.py +0 -0
  27. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/be_beamfields/propagate_sigma_matrix.py +0 -0
  28. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/be_beamfields/qgauss.py +0 -0
  29. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/be_beamfields/slicing.py +0 -0
  30. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/be_beamfields/spacecharge.py +0 -0
  31. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/elements.py +0 -0
  32. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/line.py +0 -0
  33. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/mathlibs.py +0 -0
  34. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/particles.py +0 -0
  35. {xtrack-0.44.1 → xtrack-0.46.0}/ducktrack/temp_pyparticles.py +0 -0
  36. {xtrack-0.44.1 → xtrack-0.46.0}/pyproject.toml +0 -0
  37. {xtrack-0.44.1 → xtrack-0.46.0}/setup.cfg +0 -0
  38. {xtrack-0.44.1 → xtrack-0.46.0}/setup.py +0 -0
  39. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/_temp/__init__.py +0 -0
  40. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/_temp/lhc_match/__init__.py +0 -0
  41. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/_temp/lhc_match/gen_madx_optics_file.py +0 -0
  42. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/_temp/lhc_match/lhc_match.py +0 -0
  43. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/_temp/lhc_match/var_limits.py +0 -0
  44. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/base_element.py +0 -0
  45. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/__init__.py +0 -0
  46. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/apertures.py +0 -0
  47. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/apertures_src/limitellipse.h +0 -0
  48. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/apertures_src/limitpolygon.h +0 -0
  49. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/apertures_src/limitracetrack.h +0 -0
  50. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/apertures_src/limitrect.h +0 -0
  51. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/apertures_src/limitrectellipse.h +0 -0
  52. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/apertures_src/longitudinallimitrect.h +0 -0
  53. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/beam_interaction.py +0 -0
  54. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements.py +0 -0
  55. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/bend.h +0 -0
  56. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/cavity.h +0 -0
  57. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/combinedfunctionmagnet.h +0 -0
  58. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/dipoleedge.h +0 -0
  59. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/drift.h +0 -0
  60. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/drift_elem.h +0 -0
  61. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/elens.h +0 -0
  62. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/exciter.h +0 -0
  63. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/firstordertaylormap.h +0 -0
  64. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/fringe.h +0 -0
  65. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/fringe_track.h +0 -0
  66. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/lineartransfermatrix.h +0 -0
  67. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/linesegmentmap.h +0 -0
  68. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/multipolar_kick.h +0 -0
  69. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/multipole.h +0 -0
  70. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/nonlinearlens.h +0 -0
  71. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/quadrupole.h +0 -0
  72. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/referenceenergyincrease.h +0 -0
  73. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/rfmultipole.h +0 -0
  74. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/second_order_taylor_map.h +0 -0
  75. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/sextupole.h +0 -0
  76. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/simplethinbend.h +0 -0
  77. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/simplethinquadrupole.h +0 -0
  78. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/solenoid.h +0 -0
  79. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/srotation.h +0 -0
  80. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/track_thick_bend.h +0 -0
  81. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/track_thick_cfd.h +0 -0
  82. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/track_yrotation.h +0 -0
  83. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/wedge.h +0 -0
  84. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/wedge_track.h +0 -0
  85. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/wire.h +0 -0
  86. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/xrotation.h +0 -0
  87. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/xyshift.h +0 -0
  88. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/yrotation.h +0 -0
  89. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/elements_src/zetashift.h +0 -0
  90. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/beam_elements/exciter.py +0 -0
  91. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/compounds.py +0 -0
  92. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/footprint.py +0 -0
  93. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/general.py +0 -0
  94. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/headers/atomicadd.h +0 -0
  95. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/headers/checks.h +0 -0
  96. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/headers/constants.h +0 -0
  97. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/headers/particle_states.h +0 -0
  98. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/headers/synrad_spectrum.h +0 -0
  99. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/internal_record.py +0 -0
  100. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/linear_normal_form.py +0 -0
  101. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/loss_location_refinement/__init__.py +0 -0
  102. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/loss_location_refinement/loss_location_refinement.py +0 -0
  103. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/lumi.py +0 -0
  104. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/monitors/__init__.py +0 -0
  105. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/monitors/beam_position_monitor.h +0 -0
  106. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/monitors/beam_position_monitor.py +0 -0
  107. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/monitors/beam_profile_monitor.h +0 -0
  108. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/monitors/beam_profile_monitor.py +0 -0
  109. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/monitors/beam_size_monitor.h +0 -0
  110. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/monitors/beam_size_monitor.py +0 -0
  111. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/monitors/last_turns_monitor.h +0 -0
  112. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/monitors/last_turns_monitor.py +0 -0
  113. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/monitors/particles_monitor.h +0 -0
  114. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/monitors/particles_monitor.py +0 -0
  115. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/multiline/__init__.py +0 -0
  116. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/multiline/multiline.py +0 -0
  117. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/multiline/shared_knobs.py +0 -0
  118. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/multisetter/__init__.py +0 -0
  119. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/pipeline/__init__.py +0 -0
  120. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/pipeline/core.py +0 -0
  121. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/pipeline/manager.py +0 -0
  122. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/pipeline/multitracker.py +0 -0
  123. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/prebuild_kernels.py +0 -0
  124. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/prebuilt_kernels/__init__.py +0 -0
  125. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/prebuilt_kernels/kernel_definitions.py +0 -0
  126. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/random/__init__.py +0 -0
  127. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/random/random_generators.py +0 -0
  128. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/random/random_src/exponential.h +0 -0
  129. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/random/random_src/exponential_integral_Ei.h +0 -0
  130. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/random/random_src/normal.h +0 -0
  131. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/random/random_src/rutherford.h +0 -0
  132. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/random/random_src/uniform.h +0 -0
  133. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/tapering.py +0 -0
  134. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/targets.py +0 -0
  135. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/tracker_data.py +0 -0
  136. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack/tracker_src/tracker.h +0 -0
  137. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack.egg-info/dependency_links.txt +0 -0
  138. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack.egg-info/requires.txt +0 -0
  139. {xtrack-0.44.1 → xtrack-0.46.0}/xtrack.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xtrack
3
- Version: 0.44.1
3
+ Version: 0.46.0
4
4
  Summary: Tracking library for particle accelerators
5
5
  Home-page: https://xsuite.readthedocs.io/
6
6
  Download-URL: https://pypi.python.org/pypi/xtrack
@@ -12,7 +12,8 @@ from .tracker_data import TrackerData
12
12
  from .line import Line, Node, freeze_longitudinal, _temp_knobs, EnergyProgram
13
13
  from .tracker import Tracker
14
14
  from .match import (Vary, Target, TargetList, VaryList, TargetInequality, Action,
15
- TargetRelPhaseAdvance, TargetSet, START, END)
15
+ TargetRelPhaseAdvance, TargetSet, START, END,
16
+ GreaterThan, LessThan)
16
17
  from .targets import (TargetLuminosity, TargetSeparationOrthogonalToCrossing,
17
18
  TargetSeparation)
18
19
  from .twiss import TwissInit, TwissTable
@@ -0,0 +1 @@
1
+ __version__ = '0.46.0'
@@ -10,7 +10,7 @@ import json
10
10
  from contextlib import contextmanager
11
11
  from copy import deepcopy
12
12
  from pprint import pformat
13
- from typing import List, Literal, Optional
13
+ from typing import List, Literal, Optional, Collection
14
14
 
15
15
  import numpy as np
16
16
  from scipy.constants import c as clight
@@ -22,9 +22,10 @@ import xpart as xp
22
22
  import xtrack as xt
23
23
  import xdeps as xd
24
24
  from .compounds import CompoundContainer, CompoundType, Compound, SlicedCompound
25
+ from .progress_indicator import progress
25
26
  from .slicing import Slicer
26
27
 
27
- from .survey import survey_from_tracker
28
+ from .survey import survey_from_line
28
29
  from xtrack.twiss import (compute_one_turn_matrix_finite_differences,
29
30
  find_closed_orbit_line, twiss_line,
30
31
  compute_T_matrix_line,
@@ -171,19 +172,13 @@ class Line:
171
172
 
172
173
  if isinstance(dct['elements'], dict):
173
174
  elements = {}
174
- num_elements = len(dct['elements'].keys())
175
- for ii, (kk, ee) in enumerate(dct['elements'].items()):
176
- if ii % 100 == 0:
177
- _print('Loading line from dict: '
178
- f'{round(ii/num_elements*100):2d}% ',end="\r", flush=True)
175
+ for ii, (kk, ee) in enumerate(
176
+ progress(dct['elements'].items(), desc='Loading line from dict')):
179
177
  elements[kk] = _deserialize_element(ee, class_dict, _buffer)
180
178
  elif isinstance(dct['elements'], list):
181
179
  elements = []
182
- num_elements = len(dct['elements'])
183
- for ii, ee in enumerate(dct['elements']):
184
- if ii % 100 == 0:
185
- _print('Loading line from dict: '
186
- f'{round(ii/num_elements*100):2d}% ',end="\r", flush=True)
180
+ for ii, ee in enumerate(
181
+ progress(dct['elements'], desc='Loading line from dict')):
187
182
  elements.append(_deserialize_element(ee, class_dict, _buffer))
188
183
  else:
189
184
  raise ValueError('Field `elements` must be a dict or a list')
@@ -733,6 +728,7 @@ class Line:
733
728
  turn_by_turn_monitor=None,
734
729
  freeze_longitudinal=False,
735
730
  time=False,
731
+ with_progress=False,
736
732
  **kwargs):
737
733
 
738
734
  """
@@ -770,7 +766,11 @@ class Line:
770
766
  time: bool, optional
771
767
  If True, the time taken for tracking is recorded and can be retrieved
772
768
  in `line.time_last_track`.
773
-
769
+ with_progress: bool or int, optional
770
+ If truthy, a progress bar is displayed during tracking. If an integer
771
+ is provided, it is used as the number of turns between two updates
772
+ of the progress bar. If True, 100 is taken by default. By default,
773
+ equals to False and no progress bar is displayed.
774
774
  """
775
775
 
776
776
  self._check_valid_tracker()
@@ -783,6 +783,7 @@ class Line:
783
783
  turn_by_turn_monitor=turn_by_turn_monitor,
784
784
  freeze_longitudinal=freeze_longitudinal,
785
785
  time=time,
786
+ with_progress=with_progress,
786
787
  **kwargs)
787
788
 
788
789
  def slice_thick_elements(self, slicing_strategies):
@@ -970,6 +971,12 @@ class Line:
970
971
  compute_R_element_by_element=None,
971
972
  compute_lattice_functions=None,
972
973
  compute_chromatic_properties=None,
974
+ ele_init=None,
975
+ x=None, px=None, y=None, py=None, zeta=None, delta=None,
976
+ betx=None, alfx=None, bety=None, alfy=None, bets=None,
977
+ dx=None, dpx=None, dy=None, dpy=None, dzeta=None,
978
+ mux=None, muy=None, muzeta=None,
979
+ ax_chrom=None, bx_chrom=None, ay_chrom=None, by_chrom=None,
973
980
  _continue_if_lost=None,
974
981
  _keep_tracking_data=None,
975
982
  _keep_initial_particles=None,
@@ -1142,7 +1149,7 @@ class Line:
1142
1149
  Survey table.
1143
1150
  """
1144
1151
 
1145
- return survey_from_tracker(self.tracker, X0=X0, Y0=Y0, Z0=Z0, theta0=theta0,
1152
+ return survey_from_line(self, X0=X0, Y0=Y0, Z0=Z0, theta0=theta0,
1146
1153
  phi0=phi0, psi0=psi0, element0=element0,
1147
1154
  reverse=reverse)
1148
1155
 
@@ -2618,13 +2625,7 @@ class Line:
2618
2625
  i_prev_aperture = elements_df[elements_df['is_aperture']].index[0]
2619
2626
  i_next_aperture = 0
2620
2627
 
2621
- for iee in range(i_prev_aperture, num_elements):
2622
-
2623
- if iee % 100 == 0:
2624
- _print(
2625
- f'Checking aperture: {round(iee/num_elements*100):2d}% ',
2626
- end="\r", flush=True)
2627
-
2628
+ for iee in progress(range(i_prev_aperture, num_elements), desc='Checking aperture'):
2628
2629
  if dont_need_aperture[elements_df.loc[iee, 'name']]:
2629
2630
  continue
2630
2631
 
@@ -3154,6 +3155,7 @@ class Line:
3154
3155
  fields=['hxl', 'hyl', 'length', 'radiation_flag',
3155
3156
  'delta_taper', 'voltage', 'frequency',
3156
3157
  'lag', 'lag_taper',
3158
+ 'k1',
3157
3159
  ('knl', 0), ('ksl', 0), ('knl', 1), ('ksl', 1),
3158
3160
  ('knl', 2), ('ksl', 2),
3159
3161
  ])
@@ -27,20 +27,15 @@ Loader.add_<name>(mad_elem,line,buffer) to add a new element to line
27
27
 
28
28
  if the want to control how the xobject is created
29
29
  """
30
- import abc
31
- import functools
32
- import re
33
- from itertools import zip_longest
34
- from typing import List, Iterable, Iterator, Tuple, Union
30
+ from typing import List, Union
35
31
 
36
32
  import numpy as np
37
- from math import tan
38
33
 
39
- import xtrack, xobjects
34
+ import xobjects
35
+ import xtrack
40
36
  from .compounds import Compound
41
-
42
37
  from .general import _print
43
-
38
+ from .progress_indicator import progress
44
39
 
45
40
  # Generic functions
46
41
 
@@ -691,10 +686,11 @@ class MadLoader:
691
686
  madeval = None
692
687
  self.Builder = ElementBuilder
693
688
 
694
- nelem = len(self.sequence.expanded_elements)
695
-
696
- for ii, el in enumerate(self.iter_elements(madeval=madeval)):
697
-
689
+ for ii, el in enumerate(progress(
690
+ self.iter_elements(madeval=madeval),
691
+ desc=f'Converting sequence "{self.sequence.name}"',
692
+ total=len(self.sequence.expanded_elements)),
693
+ ):
698
694
  # for each mad element create xtract elements in a buffer and add to a line
699
695
  converter = getattr(self, "convert_" + el.type, None)
700
696
  adder = getattr(self, "add_" + el.type, None)
@@ -715,14 +711,6 @@ class MadLoader:
715
711
  f'Element {el.type} not supported,\nimplement "add_{el.type}"'
716
712
  f" or convert_{el.type} in function in MadLoader"
717
713
  )
718
- if ii % 100 == 0:
719
- _print(
720
- f'Converting sequence "{self.sequence.name}":'
721
- f' {round(ii/nelem*100):2d}% ',
722
- end="\r",
723
- flush=True,
724
- )
725
- _print()
726
714
  return line
727
715
 
728
716
  def add_elements(
@@ -10,6 +10,7 @@ import xtrack as xt
10
10
  import xdeps as xd
11
11
 
12
12
  XTRACK_DEFAULT_TOL = 1e-10
13
+ XTRACK_DEFAULT_SIGMA_REL = 0.01
13
14
 
14
15
  XTRACK_DEFAULT_WEIGHTS = {
15
16
  # For quantities not specified here the default weight is 1
@@ -148,19 +149,149 @@ class ActionTwiss(xd.Action):
148
149
  ' for Multiline')
149
150
  self.line.compensate_radiation_energy_loss(verbose=False)
150
151
  if not self.allow_twiss_failure or not allow_failure:
151
- return self.line.twiss(**self.kwargs)
152
+ out = self.line.twiss(**self.kwargs)
152
153
  else:
153
154
  try:
154
- return self.line.twiss(**self.kwargs)
155
+ out = self.line.twiss(**self.kwargs)
155
156
  except Exception as ee:
156
157
  if allow_failure:
157
158
  return 'failed'
158
159
  else:
159
160
  raise ee
161
+ out.line = self.line
162
+ return out
163
+
164
+ # Alternative transitions functions
165
+ # def _transition_sigmoid_integral(x):
166
+ # x_shift = x - 3
167
+ # if x_shift > 10:
168
+ # return x_shift
169
+ # else:
170
+ # return np.log(1 + np.exp(x_shift))
171
+
172
+ # def _transition_sin(x):
173
+ # if x < 0:
174
+ # return 0
175
+ # if x < 1.:
176
+ # return 2 /np.pi - 2 /np.pi * np.cos(np.pi * x / 2)
177
+ # else:
178
+ # return x + 2 / np.pi - 1
179
+
180
+ def _poly(x):
181
+ return 3 * x**3 - 2 * x**4
182
+
183
+ def _transition_poly(x):
184
+ x_cut = 1/16 + np.sqrt(33)/16
185
+ if x < 0:
186
+ return 0
187
+ if x < x_cut:
188
+ return _poly(x)
189
+ else:
190
+ return x - x_cut + _poly(x_cut)
191
+
192
+ class GreaterThan:
193
+
194
+ _transition = staticmethod(_transition_poly)
195
+
196
+ def __init__(self, lower, mode='step', sigma=None,
197
+ sigma_rel=XTRACK_DEFAULT_SIGMA_REL):
198
+ assert mode in ['step', 'smooth']
199
+ self.lower = lower
200
+ self._value = 0.
201
+ self.mode=mode
202
+ if mode == 'smooth':
203
+ assert sigma is not None or sigma_rel is not None
204
+ if sigma is not None:
205
+ assert sigma_rel is None
206
+ self.sigma = sigma
207
+ else:
208
+ assert sigma_rel is not None
209
+ self.sigma = np.abs(self.lower) * sigma_rel
210
+
211
+ def auxtarget(self, res):
212
+ '''Transformation applied to target value to obtain the corresponding
213
+ cost function.
214
+ '''
215
+ if self.mode == 'step':
216
+ if res < self.lower:
217
+ return res - self.lower
218
+ else:
219
+ return 0
220
+ elif self.mode == 'smooth':
221
+ return self.sigma * self._transition((self.lower - res) / self.sigma)
222
+ elif self.mode == 'auxvar':
223
+ raise NotImplementedError # experimental
224
+ return res - self.lower - self.vary.container[self.vary.name]**2
225
+ else:
226
+ raise ValueError(f'Unknown mode {self.mode}')
227
+
228
+ def __repr__(self):
229
+ return f'GreaterThan({self.lower:4g})'
230
+
231
+ # Part of the `auxvar` experimental code
232
+ # def _set_value(self, val, target):
233
+ # self.lower = val
234
+ # aux_vary_container = self.vary.container
235
+ # aux_vary_container[self.vary.name] = 0
236
+ # val = target.runeval()
237
+ # if val > 0:
238
+ # aux_vary_container[self.vary.name] = np.sqrt(val)
239
+ # def gen_vary(self, container):
240
+ # self.vary = _gen_vary(container)
241
+ # return self.vary
242
+
243
+ class LessThan:
244
+
245
+ _transition = staticmethod(_transition_poly)
246
+
247
+ def __init__(self, upper, mode='step', sigma=None,
248
+ sigma_rel=XTRACK_DEFAULT_SIGMA_REL):
249
+ assert mode in ['step', 'smooth']
250
+ self.upper = upper
251
+ self._value = 0.
252
+ self.mode=mode
253
+ if mode == 'smooth':
254
+ assert sigma is not None or sigma_rel is not None
255
+ if sigma is not None:
256
+ assert sigma_rel is None
257
+ self.sigma = sigma
258
+ else:
259
+ assert sigma_rel is not None
260
+ self.sigma = np.abs(self.upper) * sigma_rel
261
+
262
+ def auxtarget(self, res):
263
+ if self.mode == 'step':
264
+ if res > self.upper:
265
+ return self.upper - res
266
+ else:
267
+ return 0
268
+ elif self.mode == 'smooth':
269
+ return self.sigma * self._transition((res - self.upper) / self.sigma)
270
+ elif self.mode == 'auxvar':
271
+ raise NotImplementedError # experimental
272
+ return self.upper - res - self.vary.container[self.vary.name]**2
273
+ else:
274
+ raise ValueError(f'Unknown mode {self.mode}')
275
+
276
+ def __repr__(self):
277
+ return f'LessThan({self.upper:4g})'
278
+
279
+ # part of the `auxvar` experimental code
280
+ # def _gen_vary(container):
281
+ # for ii in range(10000):
282
+ # if f'auxvar_{ii}' not in container:
283
+ # vv = f'auxvar_{ii}'
284
+ # break
285
+ # else:
286
+ # raise RuntimeError('Too many auxvary variables')
287
+ # container[vv] = 0
288
+ # return xt.Vary(name=vv, container=container, step=1e-3)
289
+
160
290
 
161
291
  class Target(xd.Target):
162
292
  def __init__(self, tar=None, value=None, at=None, tol=None, weight=None, scale=None,
163
- line=None, action=None, tag='', optimize_log=False, **kwargs):
293
+ line=None, action=None, tag='', optimize_log=False,
294
+ **kwargs):
164
295
 
165
296
  for kk in kwargs:
166
297
  assert kk in ALLOWED_TARGET_KWARGS, (
@@ -180,6 +311,9 @@ class Target(xd.Target):
180
311
  xdtar = (tar, at)
181
312
  else:
182
313
  xdtar = tar
314
+
315
+ self._freeze_value = None
316
+
183
317
  xd.Target.__init__(self, tar=xdtar, value=value, tol=tol,
184
318
  weight=weight, scale=scale, action=action, tag=tag,
185
319
  optimize_log=optimize_log)
@@ -196,9 +330,38 @@ class Target(xd.Target):
196
330
  if self.line is not None:
197
331
  res = res[self.line]
198
332
  if callable(self.tar):
199
- return self.tar(res)
333
+ out = self.tar(res)
200
334
  else:
201
- return res[self.tar]
335
+ out = res[self.tar]
336
+
337
+ if self._freeze_value is not None:
338
+ return out
339
+
340
+ return out
341
+
342
+ def transform(self, val):
343
+ if hasattr(self.value, 'auxtarget'):
344
+ return self.value.auxtarget(val)
345
+ else:
346
+ return val
347
+
348
+ @property
349
+ def value(self):
350
+ if self._freeze_value is not None:
351
+ return self._freeze_value
352
+ else:
353
+ return self._user_value
354
+
355
+ @value.setter
356
+ def value(self, val):
357
+ self._user_value = val
358
+
359
+ def freeze(self):
360
+ self._freeze_value = True # to bypass inequality logic
361
+ self._freeze_value = self.runeval()
362
+
363
+ def unfreeze(self):
364
+ self._freeze_value = None
202
365
 
203
366
  class Vary(xd.Vary):
204
367
  def __init__(self, name, container=None, limits=None, step=None, weight=None,
@@ -234,53 +397,43 @@ class TargetInequality(Target):
234
397
 
235
398
  def __init__(self, tar, ineq_sign, rhs, at=None, tol=None, scale=None,
236
399
  line=None, weight=None, tag=''):
237
- Target.__init__(self, tar, value=0, at=at, tol=tol, scale=scale, line=line,
238
- weight=weight, tag=tag)
239
- assert ineq_sign in ['<', '>'], ('ineq_sign must be either "<" or ">"')
240
- self.ineq_sign = ineq_sign
241
- self.rhs = rhs
242
400
 
243
- def __repr__(self):
244
- return f'TargetInequality({self.tar} {self.ineq_sign} {self.rhs}, tol={self.tol}, weight={self.weight})'
245
-
246
- def eval(self, tw):
247
- val = super().eval(tw)
248
- if self.ineq_sign == '<' and val < self.rhs:
249
- return 0
250
- elif self.ineq_sign == '>' and val > self.rhs:
251
- return 0
252
- else:
253
- return val - self.rhs
401
+ raise NotImplementedError('TargetInequality is not anymore supported. '
402
+ 'Please use Target with `GreaterThan` `LessThan` instead. '
403
+ 'For example, instead of '
404
+ 'TargetInequality("x", "<", 0.1, at="ip1") '
405
+ 'use '
406
+ 'Target("x", LessThan(0.1), at="ip1")')
254
407
 
255
408
  class TargetRelPhaseAdvance(Target):
256
409
 
257
- def __init__(self, tar, value, at_1=None, at_0=None, tag='', **kwargs):
410
+ def __init__(self, tar, value, ele_stop=None, ele_start=None, tag='', **kwargs):
258
411
 
259
412
  Target.__init__(self, tar=self.compute, value=value, tag=tag, **kwargs)
260
413
 
261
414
  assert tar in ['mux', 'muy'], 'Only mux and muy are supported'
262
415
  self.var = tar
263
- if at_1 is None:
264
- at_1 = '__ele_stop__'
265
- if at_0 is None:
266
- at_0 = '__ele_start__'
267
- self.at_1 = at_1
268
- self.at_0 = at_0
416
+ if ele_stop is None:
417
+ ele_stop = '__ele_stop__'
418
+ if ele_start is None:
419
+ ele_start = '__ele_start__'
420
+ self.ele_stop = ele_stop
421
+ self.ele_start = ele_start
269
422
 
270
423
  def __repr__(self):
271
- return f'TargetPhaseAdvance({self.var}({self.at_1}) - {self.var}({self.at_0}), value={self.value}, tol={self.tol}, weight={self.weight})'
424
+ return f'TargetPhaseAdv({self.var}({self.ele_stop} - {self.ele_start}), val={self.value}, tol={self.tol}, weight={self.weight})'
272
425
 
273
426
  def compute(self, tw):
274
427
 
275
- if self.at_1 == '__ele_stop__':
428
+ if self.ele_stop == '__ele_stop__':
276
429
  mu_1 = tw[self.var, -1]
277
430
  else:
278
- mu_1 = tw[self.var, self.at_1]
431
+ mu_1 = tw[self.var, self.ele_stop]
279
432
 
280
- if self.at_0 == '__ele_start__':
433
+ if self.ele_start == '__ele_start__':
281
434
  mu_0 = tw[self.var, 0]
282
435
  else:
283
- mu_0 = tw[self.var, self.at_0]
436
+ mu_0 = tw[self.var, self.ele_start]
284
437
 
285
438
  return mu_1 - mu_0
286
439
 
@@ -298,6 +451,9 @@ def match_line(line, vary, targets, restore_if_fail=True, solver=None,
298
451
  else:
299
452
  targets_flatten.append(tt.copy())
300
453
 
454
+ aux_vary_container = {}
455
+ aux_vary = []
456
+
301
457
  action_twiss = None
302
458
  for tt in targets_flatten:
303
459
 
@@ -342,9 +498,20 @@ def match_line(line, vary, targets, restore_if_fail=True, solver=None,
342
498
  else:
343
499
  tt.tol = default_tol
344
500
 
501
+ # part of the `auxvar` experimental code
502
+ # if isinstance(tt.value, (GreaterThan, LessThan)):
503
+ # if tt.value.mode == 'auxvar':
504
+ # aux_vary.append(tt.value.gen_vary(aux_vary_container))
505
+ # aux_vary_container[aux_vary[-1].name] = 0
506
+ # val = tt.runeval()
507
+ # if val > 0:
508
+ # aux_vary_container[aux_vary[-1].name] = np.sqrt(val)
509
+
345
510
  if not isinstance(vary, (list, tuple)):
346
511
  vary = [vary]
347
512
 
513
+ vary = list(vary) + aux_vary
514
+
348
515
  vary_flatten = _flatten_vary(vary)
349
516
  _complete_vary_with_info_from_line(vary_flatten, line)
350
517
 
@@ -114,9 +114,7 @@ class MultiSetter(xo.HybridClass):
114
114
  }
115
115
 
116
116
  def __init__(self, line, elements, field, index=None):
117
-
118
- '''
119
- Create object to efficiently set and get values of a specific field of
117
+ """Create object to efficiently set and get values of a specific field of
120
118
  several elements of a line.
121
119
 
122
120
  Parameters
@@ -129,8 +127,7 @@ class MultiSetter(xo.HybridClass):
129
127
  Name of the field to be mutated.
130
128
  index: int or None
131
129
  If the field is an array, the index of the array to be mutated.
132
-
133
- '''
130
+ """
134
131
 
135
132
  if isinstance(line, xt.Tracker):
136
133
  tracker = line
@@ -142,6 +139,13 @@ class MultiSetter(xo.HybridClass):
142
139
  tracker_buffer = tracker._buffer
143
140
  line = tracker.line
144
141
 
142
+ if len(elements) == 0:
143
+ self._empty = True
144
+ self.xoinitialize(_context=context, offsets=[])
145
+ return
146
+
147
+ self._empty = False
148
+
145
149
  # Get dtype from first element
146
150
  el = line[elements[0]]
147
151
  dd = getattr(el.copy(_context=xo.context_default), field)
@@ -178,10 +182,9 @@ class MultiSetter(xo.HybridClass):
178
182
  }[self.dtype]
179
183
 
180
184
  def get_values(self):
181
-
182
- '''
183
- Get the values of the multisetter fields.
184
- '''
185
+ """Get the values of the multisetter fields."""
186
+ if self._empty:
187
+ return self._context.zeros(0, dtype=np.float64)
185
188
 
186
189
  out = self._context.zeros(len(self.offsets), dtype=self.dtype)
187
190
  self._get_kernel.set_n_threads(len(self.offsets))
@@ -189,19 +192,19 @@ class MultiSetter(xo.HybridClass):
189
192
  return out
190
193
 
191
194
  def set_values(self, values):
192
-
193
- '''
194
- Set the values of the multisetter fields.
195
+ """Set the values of the multisetter fields.
195
196
 
196
197
  Parameters
197
198
  ----------
198
199
  values: np.ndarray
199
200
  Array of values to be set.
200
- '''
201
+ """
202
+ if self._empty:
203
+ return
201
204
 
202
205
  self._set_kernel.set_n_threads(len(self.offsets))
203
206
  self._set_kernel(data=self, buffer=self._tracker_buffer.buffer,
204
- input=xt.BeamElement._arr2ctx(self,values))
207
+ input=xt.BeamElement._arr2ctx(self, values))
205
208
 
206
209
 
207
210
  def _extract_offset(obj, field_name, index, dtype, xodtype):
@@ -0,0 +1,93 @@
1
+ from math import ceil
2
+ from typing import cast, Iterable, Collection
3
+
4
+ from .general import _print
5
+
6
+
7
+ class DefaultProgressIndicator:
8
+ """Display progress of a task.
9
+
10
+ This is a simple progress indicator, with an API that is a subset of the
11
+ one of `tqdm`. It will provide simple progress information if tqdm is
12
+ missing on the system.
13
+
14
+ Parameters
15
+ ----------
16
+ iterable: Iterable
17
+ The iterable to iterate over.
18
+ desc: str
19
+ Description of the task.
20
+ total: int, optional
21
+ Total number of iterations, if unspecified `len(iterable)` is used.
22
+ miniters: int, optional
23
+ Minimum number of iterations between updates, by default 1.
24
+ unit_scale: int, optional
25
+ Unused, kept for compatibility with tqdm. To be interpreted as the
26
+ scale by which the iteration number and `total` are multiplied: i.e.,
27
+ one iteration corresponds to `unit_scale` events.
28
+ """
29
+ def __init__(
30
+ self,
31
+ iterable: Iterable,
32
+ desc: str,
33
+ total: int = None,
34
+ miniters: int = None,
35
+ unit_scale: int = None,
36
+ ):
37
+ self.iterable = iterable
38
+ self.desc = desc
39
+ self._iterator = None
40
+ self._iteration = 0
41
+ self._total = total or len(cast(Collection, iterable))
42
+ self._update_interval = miniters or ceil(self._total / 100)
43
+ self._unit_scale = unit_scale or 1
44
+ print(f'Init: interval {self._update_interval}, total {self._total}')
45
+
46
+ def __iter__(self):
47
+ self._iterator = iter(self.iterable)
48
+ return self
49
+
50
+ def __next__(self):
51
+ if self._iteration % self._update_interval == 0:
52
+ self._print_progress()
53
+
54
+ try:
55
+ return next(self._iterator)
56
+ except StopIteration:
57
+ self._print_progress()
58
+ _print() # finish with a newline
59
+ raise
60
+ finally:
61
+ self._iteration += 1
62
+
63
+ def _print_progress(self):
64
+ percent = round(self._iteration * 100 / self._total)
65
+ index = self._iteration * self._unit_scale
66
+ scaled_total = self._total * self._unit_scale
67
+ message = f'{self.desc}: {percent:3}% ({index}/{scaled_total} iterations)'
68
+ _print(message, end='\r', flush=True)
69
+
70
+
71
+ class _ProgressIndicatorConfig:
72
+ default_indicator_cls = DefaultProgressIndicator
73
+ default_options = {}
74
+
75
+
76
+ _config = _ProgressIndicatorConfig()
77
+
78
+
79
+ def set_default_indicator(indicator_cls, **options):
80
+ _config.default_indicator_cls = indicator_cls
81
+ _config.default_options = options
82
+
83
+
84
+ def progress(iterable: Iterable, **options):
85
+ indicator = _config.default_indicator_cls
86
+ return indicator(iterable, **_config.default_options, **options)
87
+
88
+
89
+ try:
90
+ from tqdm.autonotebook import tqdm
91
+ set_default_indicator(tqdm)
92
+ except ModuleNotFoundError:
93
+ pass