xcoll 0.5.5__py3-none-any.whl → 0.5.6__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 CHANGED
@@ -7,17 +7,26 @@ from .general import _pkg_root, __version__, citation
7
7
 
8
8
  from .beam_elements import BlackAbsorber, BlackCrystal, EverestBlock, EverestCollimator, EverestCrystal, \
9
9
  BlowUp, EmittanceMonitor, collimator_classes, crystal_classes, element_classes
10
- from .install import install_elements
11
- from .line_tools import assign_optics_to_collimators, open_collimators, send_to_parking, enable_scattering, disable_scattering
12
10
  from .scattering_routines.everest import materials, Material, CrystalMaterial
13
11
  from .colldb import CollimatorDatabase
14
12
  from .interaction_record import InteractionRecord
15
13
  from .rf_sweep import RFSweep
16
- from .initial_distribution import *
17
14
  from .lossmap import LossMap
18
15
 
19
16
  # Deprecated
20
17
  from ._manager import CollimatorManager
18
+ from .install import install_elements
19
+ from .line_tools import assign_optics_to_collimators, open_collimators, send_to_parking, enable_scattering, disable_scattering
20
+ def generate_pencil_on_collimator(line, name, *args, **kwargs):
21
+ from warnings import warn
22
+ warn("`xcoll.generate_pencil_on_collimator()` is deprecated and will be removed. Use "
23
+ + "`line[coll].generate_pencil()` instead.", FutureWarning)
24
+ return line[name].generate_pencil(*args, **kwargs)
25
+ def generate_delta_from_dispersion(line, at_element, *args, **kwargs):
26
+ from warnings import warn
27
+ warn("`xcoll.generate_delta_from_dispersion()` is deprecated and will be removed. Use "
28
+ + "`line[at_element].generate_delta()` instead.", FutureWarning)
29
+ return line[name].generate_delta(*args, **kwargs)
21
30
 
22
31
  # print("If you use Xcoll in your simulations, please cite us :-)")
23
32
  # print(citation)
@@ -21,5 +21,7 @@ crystal_classes = tuple(v for v in globals().values()
21
21
 
22
22
  element_classes = block_classes + (BlowUp, EmittanceMonitor)
23
23
 
24
+ # For compatibility with _K2Collimators
25
+ _all_block_classes = block_classes
24
26
  _all_collimator_classes = collimator_classes
25
27
  _all_crystal_classes = crystal_classes
@@ -922,6 +922,31 @@ class BaseCollimator(BaseBlock):
922
922
  # Methods
923
923
  # =======
924
924
 
925
+ def generate_pencil(self, num_particles, *, side='+-', pencil_spread=1e-6,
926
+ impact_parameter=0, sigma_z=7.61e-2, twiss=None, longitudinal=None,
927
+ longitudinal_betatron_cut=None, tw=None, **kwargs):
928
+ if not hasattr(self, '_line') or not hasattr(self, '_name'):
929
+ raise ValueError("Collimator is missing a pointer to the line. Install collimators "
930
+ + "with `line.collimators.install()` (or use "
931
+ + "`xcoll.initial_distribution.generate_pencil_on_collimator()`).")
932
+ from xcoll.initial_distribution import generate_pencil_on_collimator
933
+ return generate_pencil_on_collimator(line=self._line, name=self._name, side=side,
934
+ num_particles=num_particles, pencil_spread=pencil_spread, tw=tw,
935
+ impact_parameter=impact_parameter, sigma_z=sigma_z, twiss=twiss,
936
+ longitudinal=longitudinal, longitudinal_betatron_cut=longitudinal_betatron_cut,
937
+ **kwargs)
938
+
939
+ def generate_delta(self, *, plane, position_mm, nemitt_x, nemitt_y, betatron_cut=0,
940
+ match_at_front=True, twiss=None):
941
+ if not hasattr(self, '_line') or not hasattr(self, '_name'):
942
+ raise ValueError("Collimator is missing a pointer to the line. Install collimators "
943
+ + "with `line.collimators.install()` (or use "
944
+ + "`xcoll.initial_distribution.generate_delta_from_dispersion()`).")
945
+ from xcoll.initial_distribution import generate_delta_from_dispersion
946
+ return generate_delta_from_dispersion(line=self._line, at_element=self._name, plane=plane,
947
+ position_mm=position_mm, nemitt_x=nemitt_x, nemitt_y=nemitt_y, twiss=twiss,
948
+ betatron_cut=betatron_cut, match_at_front=match_at_front)
949
+
925
950
  def _verify_consistency(self):
926
951
  BaseBlock._verify_consistency(self)
927
952
  # Verify angles
@@ -1345,6 +1370,9 @@ class BaseCrystal(BaseBlock):
1345
1370
  # Methods
1346
1371
  # =======
1347
1372
 
1373
+ def generate_pencil(self, **kwargs):
1374
+ return BaseCollimator.generate_pencil(self, **kwargs)
1375
+
1348
1376
  def _verify_consistency(self):
1349
1377
  BaseBlock._verify_consistency(self)
1350
1378
  # Verify angles
xcoll/colldb.py CHANGED
@@ -14,7 +14,6 @@ import xtrack as xt
14
14
 
15
15
  from .beam_elements import BlackAbsorber, BlackCrystal, EverestCollimator, EverestCrystal, \
16
16
  BaseCollimator, BaseCrystal, _all_collimator_classes
17
- from .install import install_elements
18
17
  from .scattering_routines.everest.materials import SixTrack_to_xcoll
19
18
 
20
19
 
@@ -572,7 +571,7 @@ class CollimatorDatabase:
572
571
  else:
573
572
  self._create_crystal(line, BlackCrystal, name, verbose=verbose)
574
573
  elements = [self._elements[name] for name in names]
575
- install_elements(line, names, elements, need_apertures=need_apertures)
574
+ line.collimators.install(names, elements, need_apertures=need_apertures)
576
575
 
577
576
  def install_everest_collimators(self, line, *, names=None, families=None, verbose=False, need_apertures=True):
578
577
  names = self._get_names_from_line(line, names, families)
@@ -586,7 +585,7 @@ class CollimatorDatabase:
586
585
  lattice=self[name]['crystal'], verbose=verbose,
587
586
  miscut=self[name]['miscut'])
588
587
  elements = [self._elements[name] for name in names]
589
- install_elements(line, names, elements, need_apertures=need_apertures)
588
+ line.collimators.install(names, elements, need_apertures=need_apertures)
590
589
 
591
590
 
592
591
  # ==================================
xcoll/general.py CHANGED
@@ -12,5 +12,5 @@ citation = "F.F. Van der Veken, et al.: Recent Developments with the New Tools f
12
12
  # ======================
13
13
  # Do not change
14
14
  # ======================
15
- __version__ = '0.5.5'
15
+ __version__ = '0.5.6'
16
16
  # ======================
@@ -4,6 +4,7 @@
4
4
  # ######################################### #
5
5
 
6
6
  import numpy as np
7
+ from warnings import warn
7
8
 
8
9
  import xtrack as xt
9
10
  import xobjects as xo
@@ -14,7 +15,7 @@ from .beam_elements import _all_collimator_classes, EverestCrystal
14
15
 
15
16
  def generate_pencil_on_collimator(line, name, num_particles, *, side='+-', pencil_spread=1e-6,
16
17
  impact_parameter=0, sigma_z=7.61e-2, twiss=None, longitudinal=None,
17
- longitudinal_betatron_cut=None, tw=None):
18
+ longitudinal_betatron_cut=None, tw=None, **kwargs):
18
19
  """
19
20
  Generate a pencil beam on a collimator.
20
21
  """
@@ -49,7 +50,7 @@ def generate_pencil_on_collimator(line, name, num_particles, *, side='+-', penci
49
50
  raise NotImplementedError("Pencil beam on a skew collimator not yet supported!")
50
51
 
51
52
  if tw is not None:
52
- print("The argument tw is deprecated. Please use twiss instead.")
53
+ warn("The argument tw is deprecated. Please use twiss instead.", FutureWarning)
53
54
  if twiss is None:
54
55
  twiss = tw
55
56
 
@@ -129,15 +130,13 @@ def generate_pencil_on_collimator(line, name, num_particles, *, side='+-', penci
129
130
  part = xp.build_particles(
130
131
  x=pencil, px=p_pencil, y_norm=transverse_norm, py_norm=p_transverse_norm,
131
132
  zeta=zeta, delta=delta, nemitt_x=coll.nemitt_x, nemitt_y=coll.nemitt_y,
132
- line=line, at_element=at_element, #match_at_s=match_at_s,
133
- _context=coll._buffer.context
133
+ line=line, at_element=at_element, _context=coll._buffer.context, **kwargs
134
134
  )
135
135
  else:
136
136
  part = xp.build_particles(
137
137
  x_norm=transverse_norm, px_norm=p_transverse_norm, y=pencil, py=p_pencil,
138
138
  zeta=zeta, delta=delta, nemitt_x=coll.nemitt_x, nemitt_y=coll.nemitt_y,
139
- line=line, at_element=at_element, #match_at_s=match_at_s,
140
- _context=coll._buffer.context
139
+ line=line, at_element=at_element, _context=coll._buffer.context, **kwargs
141
140
  )
142
141
 
143
142
  part._init_random_number_generator()
xcoll/install.py CHANGED
@@ -3,177 +3,33 @@
3
3
  # Copyright (c) CERN, 2024. #
4
4
  # ######################################### #
5
5
 
6
- import numpy as np
7
- import xtrack as xt
6
+ from warnings import warn
8
7
 
9
- from .beam_elements import element_classes
8
+ # This file is deprecated and will be removed in the future.
10
9
 
11
- def install_elements(line, names, elements, *, at_s=None, apertures=None, need_apertures=False, s_tol=1.e-6):
12
- if line._has_valid_tracker():
13
- raise Exception("Tracker already built!\nPlease install collimators before building "
14
- + "tracker!")
15
-
16
- if not hasattr(names, '__iter__') or isinstance(names, str):
17
- names = [names]
18
- if not hasattr(elements, '__iter__') or isinstance(elements, str):
19
- elements = [elements]
20
- names = np.array(names)
21
- length = np.array([coll.length for coll in elements])
22
- assert len(length) == len(names)
23
- if not hasattr(at_s, '__iter__'):
24
- at_s = [at_s for _ in range(len(names))]
25
- assert len(at_s) == len(names)
26
- if isinstance(apertures, str) or not hasattr(apertures, '__iter__'):
27
- apertures = [apertures for _ in range(len(names))]
28
- assert len(apertures) == len(names)
29
-
30
- # Verify elements
31
- for el in elements:
32
- assert isinstance(el, element_classes)
33
- el._tracking = False
34
-
35
- # Get positions
36
- tab = line.get_table()
37
- tt = tab.rows[[name for name in names if name in line.element_names]]
38
- s_start = []
39
- for name, s, l in zip(names, at_s, length):
40
- if s is None:
41
- s_start.append(_get_s_start(line, name, l, tt))
42
- else:
43
- s_start.append(s)
44
- s_start = np.array(s_start)
45
- s_end = s_start + length
46
-
47
- # Check positions
48
- l_line = line.get_length()
49
- for s1, s2, name, s3 in zip(s_start, s_end, names, at_s):
50
- check_element_position(line, name, s1, s2, s3, l_line, s_tol=s_tol)
51
-
52
- # Look for apertures
53
- aper_upstream = []
54
- aper_downstream = []
55
- for s1, s2, name, aper in zip(s_start, s_end, names, apertures):
56
- if not need_apertures:
57
- aper_upstream.append(None)
58
- aper_downstream.append(None)
59
- else:
60
- aper1, aper2 = get_aperture_for_element(line, name, s1, s2, aper, tab, s_tol=s_tol)
61
- aper_upstream.append(aper1)
62
- aper_downstream.append(aper2)
63
-
64
- # Remove elements at location of collimator (by changing them into markers)
65
- for s1, s2, name in zip(s_start, s_end, names):
66
- prepare_space_for_element(line, name, s1, s2, tab=tab, s_tol=s_tol)
67
-
68
- # Install
69
- line._insert_thick_elements_at_s(element_names=list(names), elements=elements, at_s=s_start, s_tol=s_tol)
70
-
71
- # Install apertures
72
- if need_apertures:
73
- for s1, name, aper1, aper2 in zip(s_start, names, aper_upstream, aper_downstream):
74
- line.insert_element(element=aper1, name=f'{name}_aper_upstream', at=name, s_tol=s_tol)
75
- idx = line.element_names.index(name) + 1
76
- line.insert_element(element=aper2, name=f'{name}_aper_downstream', at=idx, s_tol=s_tol)
77
-
78
-
79
- def _get_s_start(line, name, length, tab=None):
80
- if tab is None:
81
- tab = line.get_table()
82
- if name in line.element_names and hasattr(line[name], 'length'):
83
- existing_length = line[name].length
84
- else:
85
- existing_length = 0
86
- if name not in tab.name:
87
- raise ValueError(f"Element {name} not found in line. Need to mmanually provide `at_s`.")
88
- return tab.rows[name].s[0] + existing_length/2. - length/2
89
10
 
11
+ def install_elements(line, names, elements, *, at_s=None, apertures=None, need_apertures=False, s_tol=1.e-6):
12
+ warn("The function xcoll.install_elements() is deprecated and will be removed in the future. "
13
+ + "Please use line.collimators.install() instead.", FutureWarning)
14
+ line.collimators.install(names=names, elements=elements, at_s=at_s, apertures=apertures,
15
+ need_apertures=need_apertures, s_tol=s_tol)
90
16
 
91
17
  def check_element_position(line, name, s_start, s_end, at_s, length=None, s_tol=1.e-6):
92
- if at_s is None:
93
- if name not in line.element_names:
94
- raise ValueError(f"Element {name} not found in line. Provide `at_s`.")
95
- elif name in line.element_names:
96
- if at_s < s_start or at_s > s_end:
97
- raise ValueError(f"Element {name} already exists in line at different "
98
- + f"location: at_s = {at_s}, exists at [{s_start}, {s_end}].")
99
- if length is None:
100
- length = line.get_length()
101
- if s_start <= s_tol:
102
- raise ValueError(f"Position of {name} too close to start of line. Please cycle.")
103
- if s_end >= length - s_tol:
104
- raise ValueError(f"Position of {name} too close to end of line. Please cycle.")
105
-
18
+ warn("The function xcoll.check_element_position() is deprecated and will be removed "
19
+ + "in the future. Please use line.collimators.check_position() instead.", FutureWarning)
20
+ return line.collimators.check_position(name, s_start, s_end, at_s, length=length, s_tol=s_tol)
106
21
 
107
22
  def get_apertures_at_s(tab, s, s_tol=1.e-6):
108
- tab_s = tab.rows[s-s_tol:s+s_tol:'s']
109
- aper = tab_s.rows[[cls.startswith('Limit') for cls in tab_s.element_type]]
110
- if len(aper) == 0:
111
- return None
112
- elif len(aper) == 1:
113
- return aper.name[0]
114
- else:
115
- raise ValueError(f"Multiple apertures found at location {s} with "
116
- + f"tolerance {s_tol}: {aper.name}. Not supported.")
117
-
23
+ warn("The function xcoll.get_apertures_at_s() is deprecated and will be removed in the future. "
24
+ + "Please use line.collimators.get_apertures_at_s() instead.", FutureWarning)
25
+ return get_apertures_at_s(s, s_tol=s_tol)
118
26
 
119
27
  def get_aperture_for_element(line, name, s_start, s_end, aperture=None, tab=None, s_tol=1.e-6):
120
- if aperture is not None:
121
- if isinstance(aperture, str):
122
- aper1 = line[aperture]
123
- aper2 = line[aperture]
124
- elif hasattr(aperture, '__iter__'):
125
- if len(aperture) != 2:
126
- raise ValueError(f"The value `aperture` should be None or a list "
127
- + f"[upstream, downstream].")
128
- assert aperture[0] is not None and aperture[1] is not None
129
- if isinstance(aperture[0], str):
130
- aper1 = line[aperture[0]]
131
- if isinstance(aperture[1], str):
132
- aper2 = line[aperture[1]]
133
- else:
134
- aper1 = aperture
135
- aper2 = aperture
136
- if not xt.line._is_aperture(aper1, line):
137
- raise ValueError(f"Not a valid aperture: {aper1}")
138
- if not xt.line._is_aperture(aper2, line):
139
- raise ValueError(f"Not a valid aperture: {aper2}")
140
- return aper1.copy(), aper2.copy()
141
- else:
142
- if tab is None:
143
- tab = line.get_table()
144
- aper1 = get_apertures_at_s(tab, s_start, s_tol=s_tol)
145
- aper2 = get_apertures_at_s(tab, s_end, s_tol=s_tol)
146
- if aper1 is None and aper2 is not None:
147
- aper1 = aper2
148
- print(f"Warning: Could not find upstream aperture for {name}! "
149
- + f"Used copy of downstream aperture. Proceed with caution.")
150
- elif aper2 is None and aper1 is not None:
151
- aper2 = aper1
152
- print(f"Warning: Could not find downstream aperture for {name}! "
153
- + f"Used copy of upstream aperture. Proceed with caution.")
154
- elif aper1 is None and aper2 is None:
155
- aper_mid = get_apertures_at_s(tab, (s_start+s_end)/2, s_tol=s_tol)
156
- if aper_mid is None:
157
- raise ValueError(f"No aperture found for {name}! Please provide one.")
158
- if line[aper_mid].allow_rot_and_shift \
159
- and xt.base_element._tranformations_active(line[aper_mid]):
160
- print(f"Warning: Using the centre aperture for {name}, but "
161
- + f"transformations are present. Proceed with caution.")
162
- aper1 = aper_mid
163
- aper2 = aper_mid
164
- return line[aper1].copy(), line[aper2].copy()
165
-
28
+ warn("The function xcoll.get_aperture_for_element() is deprecated and will be removed in the future. "
29
+ + "Please use line.collimators.get_aperture() instead.", FutureWarning)
30
+ return line.get_aperture(name, s_start, s_end, aperture=aperture, tab=tab, s_tol=s_tol)
166
31
 
167
32
  def prepare_space_for_element(line, name, s_start, s_end, tab=None, s_tol=1.e-6):
168
- if tab is None:
169
- tab = line.get_table()
170
- tt = tab.rows[s_start-s_tol:s_end+s_tol:'s']
171
- for element_name, element_type in zip(tt.name[:-1], tt.element_type[:-1]):
172
- if element_type == 'Marker' or element_type.startswith('Drift'):
173
- continue
174
- if not element_type.startswith('Limit'):
175
- print(f"Warning: Removed active element {element_name} "
176
- + f"at location inside collimator {name}!")
177
- length = line[element_name].length if hasattr(line[element_name], 'length') else 0
178
- line.element_dict[element_name] = xt.Drift(length=length)
179
-
33
+ warn("The function xcoll.prepare_space_for_element() is deprecated and will be removed in the future. "
34
+ + "Please use line.collimators.prepare_space() instead.", FutureWarning)
35
+ return line.collimators.prepare_space(name, s_start, s_end, tab=tab, s_tol=s_tol)