xcoll 0.6.2__py3-none-any.whl → 0.6.4__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
@@ -11,7 +11,7 @@ from .beam_elements import BlackAbsorber, BlackCrystal, TransparentCollimator, T
11
11
  from .scattering_routines.everest import materials, Material, CrystalMaterial
12
12
  from .colldb import CollimatorDatabase
13
13
  from .interaction_record import InteractionRecord
14
- from .rf_sweep import RFSweep
14
+ from .rf_sweep import RFSweep, prepare_rf_sweep
15
15
  from .lossmap import LossMap, MultiLossMap
16
16
 
17
17
 
@@ -0,0 +1,23 @@
1
+ // copyright ############################### #
2
+ // This file is part of the Xcoll package. #
3
+ // Copyright (c) CERN, 2025. #
4
+ // ######################################### #
5
+
6
+ #ifndef XCOLL_RF_SWEEP_H
7
+ #define XCOLL_RF_SWEEP_H
8
+
9
+ /*gpufun*/
10
+ void RFSweep_track_local_particle(RFSweepData el, LocalParticle* part0){
11
+ double const step = RFSweepData_get__rf_sweep_df_step(el); // L*df/(f0 + df)
12
+ int64_t const start_turn = RFSweepData_get_start_turn(el);
13
+ int64_t const stop_turn = RFSweepData_get_stop_turn(el);
14
+
15
+ //start_per_particle_block (part0->part)
16
+ int64_t at_turn = LocalParticle_get_at_turn(part);
17
+ if (at_turn >= start_turn && at_turn <= stop_turn){
18
+ LocalParticle_add_to_zeta(part, -(at_turn - start_turn + 1)*step);
19
+ }
20
+ //end_per_particle_block
21
+ }
22
+
23
+ #endif /* XCOLL_RF_SWEEP_H */
File without changes
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.6.2'
15
+ __version__ = '0.6.4'
16
16
  # ======================
xcoll/geometry.md ADDED
@@ -0,0 +1,42 @@
1
+ PSEUDOCODE for material interactions tracking in collimator
2
+ ===========================================================
3
+
4
+ - create DriftTrajectory from particle
5
+ - loop:
6
+ - find first crossing with collimator shape (segments)
7
+ - if distance larger than end of BeamElement -> move particle to exendit and break loop
8
+ - move particle to collimator impact point
9
+ - create MCSTrajectory from new particle
10
+ - loop:
11
+ - find first crossing with collimator shape (segments)
12
+ - do not move, but calculate path length
13
+ - compare to distance to nuclear interaction
14
+ - shortest wins (nuclear or exit)
15
+ - move to next point
16
+ - when at exit, create DriftTrajectory from particle
17
+
18
+
19
+
20
+ PSEUDOCODE for material interactions tracking in crystal
21
+ ========================================================
22
+
23
+ - create DriftTrajectory from particle
24
+ - loop:
25
+ - find first crossing with crystal shape (segments)
26
+ - if distance larger than end of BeamElement -> move particle to end and break loop
27
+ - move particle to crystal impact point
28
+ - create MCSTrajectory (if amorphous) or CircularTrajectory (if channelling) from new particle
29
+ - loop:
30
+ - find first crossing with crystal shape (segments)
31
+ - do not move, but calculate path length
32
+ - compare to distance to nuclear interaction and dechannelling
33
+ - shortest wins (nuclear, dechannelling, or exit)
34
+ - move to next point
35
+ - when at exit, create DriftTrajectory from particle
36
+
37
+
38
+ PSEUDOCODE for crossing finder
39
+ ==============================
40
+
41
+ - if DriftTrajectory and any segment
42
+ => use analytical
@@ -0,0 +1,7 @@
1
+ # copyright ############################### #
2
+ # This file is part of the Xcoll package. #
3
+ # Copyright (c) CERN, 2025. #
4
+ # ######################################### #
5
+
6
+ from .elements import DEFAULT_XCOLL_ELEMENTS
7
+ from .element_inits import XCOLL_ELEMENTS_INIT_DEFAULTS
@@ -0,0 +1,6 @@
1
+ # copyright ############################### #
2
+ # This file is part of the Xcoll package. #
3
+ # Copyright (c) CERN, 2025. #
4
+ # ######################################### #
5
+
6
+ XCOLL_ELEMENTS_INIT_DEFAULTS = {}
@@ -0,0 +1,20 @@
1
+ # copyright ############################### #
2
+ # This file is part of the Xcoll package. #
3
+ # Copyright (c) CERN, 2025. #
4
+ # ######################################### #
5
+
6
+ from ..beam_elements import *
7
+
8
+
9
+ DEFAULT_XCOLL_ELEMENTS = [
10
+ BlackAbsorber,
11
+ BlackCrystal,
12
+ TransparentCollimator,
13
+ TransparentCrystal,
14
+ EverestBlock,
15
+ EverestCollimator,
16
+ EverestCrystal,
17
+ BlowUp,
18
+ # ParticleStatsMonitor,
19
+ EmittanceMonitor
20
+ ]
xcoll/rf_sweep.py CHANGED
@@ -1,197 +1,194 @@
1
1
  # copyright ############################### #
2
2
  # This file is part of the Xcoll package. #
3
- # Copyright (c) CERN, 2024. #
3
+ # Copyright (c) CERN, 2025. #
4
4
  # ######################################### #
5
5
 
6
6
  import numpy as np
7
+ from warnings import warn
7
8
  import scipy.constants as sc
8
- from time import perf_counter
9
9
 
10
10
  import xtrack as xt
11
- from xtrack.progress_indicator import progress
12
11
 
13
- class RFSweep:
14
12
 
15
- def __init__(self, line):
16
- self.line = line
17
- self._get_base_frequency()
18
- self._install_zeta_shift()
19
- self.reset()
20
-
21
- def _get_base_frequency(self):
22
- self.cavities = self.line.get_elements_of_type(xt.Cavity)[1]
23
- freq = np.unique([round(self.line[cav].frequency, 9) for cav in self.cavities])
24
- if len(freq) > 1:
25
- raise NotImplementedError(f"Cannot sweep multiple cavities with different frequencies!")
26
- elif abs(freq[0]) < 1e-9 :
27
- raise ValueError(f"Cavity frequency not set!")
28
- self.f_RF = freq[0]
29
- phi = np.unique(np.array([self.line[cav].lag for cav in self.cavities])*np.pi/180.)
30
- if len(phi) > 1:
31
- raise NotImplementedError(f"Cannot sweep multiple cavities with different phases!")
32
- self.phi = phi[0]
33
- self.V = np.array([self.line[cav].voltage for cav in self.cavities]).sum()
34
- self.L = self.line.get_length()
13
+ def prepare_rf_sweep(line, *, cavities=None, sweep=None, sweep_per_turn=None, num_turns=None):
14
+ rf_sweep = RFSweep(line=line, cavities=cavities)
15
+ rf_sweep.prepare(sweep=sweep, sweep_per_turn=sweep_per_turn, num_turns=num_turns)
35
16
 
36
- def _install_zeta_shift(self):
37
- if 'rf_sweep' in self.line.element_names:
38
- print(f"Found existing RF sweep in line.")
39
- else:
40
- s_cav = min([self.line.get_s_position(cav) for cav in self.cavities])
41
- if self.line.tracker is not None:
42
- self.line.unfreeze()
43
- line_was_built = True
44
- else:
45
- line_was_built = False
46
- self.line.insert_element(element=xt.ZetaShift(dzeta=0), name='rf_sweep', at_s=s_cav)
47
- if line_was_built:
48
- self.line.build_tracker()
17
+
18
+ class RFSweep:
19
+ def __init__(self, line, cavities=None):
20
+ self.line = line
21
+ if line.env.ref_manager is None:
22
+ raise ValueError("Environment must have a `ref_manager` to use RFSweep!" \
23
+ + "Do not use `optimize_for_tracking` as it will "
24
+ + "disable expressions, which are needed for RFSweep.")
25
+ line.enable_time_dependent_vars = False # To be able to twiss in the prepare step
26
+ self.env = line.env
27
+ self.cavities = cavities
28
+ self.env['rf_sweep_df'] = 0
29
+ self._prepared = False
49
30
 
50
31
  @property
51
32
  def current_sweep_value(self):
52
- dzeta = self.line['rf_sweep'].dzeta
53
- return round(self.f_RF * dzeta/(self.L-dzeta), 6)
54
-
55
-
56
- def info(self, sweep=0, num_turns=0):
57
- if abs(sweep) > 1e-9:
58
- existing_sweep = self.current_sweep_value
59
-
60
- beta0 = self.line.particle_ref.beta0[0]
61
- E = self.line.particle_ref.energy0[0]
62
- q = self.line.particle_ref.q0
63
- h = self.f_RF * self.L / beta0 / sc.c
64
- tw = self.line.twiss()
65
- eta = tw.slip_factor
66
-
67
- bucket_height = np.sqrt(abs(q*self.V*beta0**2 / (np.pi*h*eta*E) * (
68
- 2*np.cos(self.phi) + (2*self.phi-np.pi)*np.sin(self.phi)
69
- )))
70
- delta_shift = -sweep / self.f_RF / eta
71
- bucket_shift = delta_shift / bucket_height / 2
72
- if num_turns > 0:
73
- rf_shift_per_turn = sweep / num_turns
74
- print(f"The current frequency is {self.f_RF + existing_sweep}Hz, adding {rf_shift_per_turn}Hz "
75
- + f"per turn until {self.f_RF + existing_sweep + sweep} (for {num_turns} turns).")
76
- print(f"This sweep will move the center of the bucket with \u0394\u03B4 = "
77
- + f"{delta_shift} ({bucket_shift} buckets).")
78
- if num_turns > 0 and num_turns < 3*bucket_shift/tw.qs:
79
- print(f"Warning: This is a very fast sweep, moving ~{round(bucket_shift, 2)} buckets in "
80
- + f"~{round(num_turns*tw.qs, 2)} synchrotron oscillations (on average). If the "
81
- + f"bucket moves faster than a particle can follow, that particle will move out of "
82
- + f"the bucket and remain uncaptured.")
83
-
33
+ return self.env['rf_sweep_df']
34
+
35
+ def prepare(self, *, sweep=None, num_turns=None, sweep_per_turn=None):
36
+ # TODO: if using sweep and num_turns, the sweep should stop after num_turns,
37
+ # but if using sweep_per_turn, it should continue indefinitely.
38
+ if not self._prepared:
39
+ if sweep_per_turn is not None:
40
+ if np.isclose(sweep_per_turn, 0):
41
+ raise ValueError("Variable `sweep_per_turn` must be non-zero!")
42
+ if sweep is not None:
43
+ raise ValueError("Provide either `sweep` or `sweep_per_turn`, not both.")
44
+ if num_turns is not None:
45
+ raise ValueError("Variable `num_turns` cannot be set when using `sweep_per_turn`.")
46
+ self.sweep_per_turn = sweep_per_turn
47
+ elif sweep is not None:
48
+ if np.isclose(sweep, 0):
49
+ raise ValueError("Variable `sweep` must be non-zero!")
50
+ if num_turns is None:
51
+ num_turns = int(abs(sweep))
52
+ if num_turns <= 0:
53
+ raise ValueError("When using `sweep`, `num_turns` must be a positive integer.")
54
+ self.sweep_per_turn = sweep / num_turns
55
+ else:
56
+ raise ValueError("Either `sweep` or `sweep_per_turn` must be provided.")
57
+ self._get_cavity_data()
58
+ self._install_zeta_shift()
59
+ self.tw = self.line.twiss()
60
+ self.reset() # Initialize rf_sweep_df
61
+ self.env['rf_sweep'].dzeta = f"{self.L} * rf_sweep_df / ({self.f_RF} + rf_sweep_df)"
62
+ for cavs in self.cavities:
63
+ for cav in cavs['names']:
64
+ scale_factor = int(np.round(cavs['freq'] / self.f_RF))
65
+ if scale_factor == 1:
66
+ self.env.ref[cav].frequency += self.env.ref["rf_sweep_df"]
67
+ else:
68
+ self.env.ref[cav].frequency += scale_factor * self.env.ref["rf_sweep_df"]
69
+ self.line.enable_time_dependent_vars = True
70
+ print("Enabled time-dependent variables in the line.")
71
+ self._prepared = True
84
72
 
85
- def track(self, sweep=0, particles=None, num_turns=0, verbose=True, *args, **kwargs):
86
73
 
87
- # Was there a previous sweep?
88
- # If yes, we do not overwrite it but continue from there
74
+ def reset(self):
75
+ if self.sweep_per_turn is None:
76
+ raise ValueError("RFSweep not prepared. Call `prepare` first.")
77
+ t_turn = self.tw.T_rev0 # To start sweeping from turn 0
78
+ current_time = self.env['t_turn_s']
79
+ if current_time == 0:
80
+ self.env['rf_sweep_df'] = f"(t_turn_s + {t_turn}) / {t_turn} * {self.sweep_per_turn}"
81
+ else:
82
+ self.env['rf_sweep_df'] = f"(t_turn_s - {current_time} + {t_turn}) / {t_turn} * {self.sweep_per_turn}"
83
+
84
+
85
+ def info(self, sweep=None, num_turns=None):
86
+ if sweep is not None or num_turns is not None:
87
+ if sweep is not None:
88
+ warn("The `sweep` argument is deprecated.", DeprecationWarning)
89
+ if num_turns is not None:
90
+ warn("The `num_turns` argument is deprecated.", DeprecationWarning)
91
+ self.prepare(sweep=sweep, num_turns=num_turns)
92
+ if self.sweep_per_turn is None:
93
+ raise ValueError("RFSweep not prepared. Call `prepare` first.")
89
94
  existing_sweep = self.current_sweep_value
90
95
 
91
- # Just set the new RF frequency, no tracking
92
- if num_turns == 0:
93
- sweep += existing_sweep
94
- if verbose:
95
- print(f"The current frequency is {self.f_RF + existing_sweep}Hz, moving to {self.f_RF + sweep}Hz."
96
- + "No tracking performed.")
97
- self.line['rf_sweep'].dzeta = self.L * sweep / (self.f_RF + sweep)
98
-
99
- # Sweep and track
96
+ beta0 = self.line.particle_ref.beta0[0]
97
+ E = self.line.particle_ref.energy0[0]
98
+ q = self.line.particle_ref.q0
99
+ h = self.f_RF * self.L / beta0 / sc.c
100
+ eta = self.tw.slip_factor
101
+
102
+ bucket_height = np.sqrt(abs(q*self.V*beta0**2 / (np.pi*h*eta*E) * (
103
+ 2*np.cos(self.phi) + (2*self.phi-np.pi)*np.sin(self.phi)
104
+ )))
105
+ delta_shift = -self.sweep_per_turn / self.f_RF / eta
106
+ bucket_turns = bucket_height * 2 / abs(delta_shift)
107
+ print(f"The current frequency is {self.f_RF + existing_sweep}Hz, adding "
108
+ + f"{self.sweep_per_turn}Hz per turn.")
109
+ print(f"This sweep will move the center of the bucket with \u0394\u03B4 = "
110
+ + f"{delta_shift:.4} per turn.")
111
+ print(f"The bucket height is {bucket_height:.4}, so this implies the sweep "
112
+ + f"will shift one bucket every {round(bucket_turns, 2)} turns.")
113
+ if self.tw.qs * bucket_turns < 3:
114
+ print(f"Warning: This is a very fast sweep, moving ~1 bucket in "
115
+ + f"~{round(self.tw.qs * bucket_turns, 2)} synchrotron oscillations "
116
+ + f"(on average). If the bucket moves faster than a particle "
117
+ + f"can follow, that particle will move out of the bucket and "
118
+ + f"remain uncaptured.")
119
+
120
+
121
+ # For backward compatibility
122
+ def track(self, sweep=0, particles=None, num_turns=0, verbose=True, *args, **kwargs):
123
+ warn("Using RFSweep.track() is deprecated. Please use RFSweep.prepare() "
124
+ + "and then xt.Line.track().", DeprecationWarning)
125
+ self.prepare(sweep=sweep, num_turns=num_turns)
126
+ self.line.track(particles=particles, num_turns=num_turns, *args, **kwargs)
127
+
128
+
129
+ def _get_cavity_data(self):
130
+ # Cavity data not yet extracted
131
+ tt = self.line.get_table()
132
+ tt_c = tt.rows[[nn for nn, ttt in zip(tt.name, tt.element_type)
133
+ if 'Cavity' in ttt and 'CrabCavity' not in ttt]]
134
+ mask = tt_c.parent_name == None # Unsliced cavities
135
+ if self.cavities is None:
136
+ self.cavities = np.unique(list(tt_c.name[mask]) + list(tt_c.parent_name[~mask]))
100
137
  else:
101
- if self.line.tracker is None:
102
- raise ValueError("Need to build tracker first!")
103
- if particles is None:
104
- raise ValueError("Need particles to track!")
105
- time = kwargs.pop('time', False)
106
- with_progress = kwargs.pop('with_progress', False)
107
- rf_shift_per_turn = sweep / num_turns
108
-
109
- # This is taken from xtrack.tracker.Tracker._track
110
- if time:
111
- t0 = perf_counter()
112
- if with_progress:
113
- if self.line.tracker.enable_pipeline_hold:
114
- raise ValueError("Progress indicator is not supported with pipeline hold")
115
- if num_turns < 2:
116
- raise ValueError('Tracking with progress indicator is only '
117
- 'possible over more than one turn.')
118
- if with_progress is True:
119
- batch_size = scaling = 100
120
- else:
121
- batch_size = int(with_progress)
122
- scaling = with_progress if batch_size > 1 else None
123
- if kwargs.get('turn_by_turn_monitor') is True:
124
- ele_start = kwargs.get('ele_start') or 0
125
- ele_stop = kwargs.get('ele_stop')
126
- if ele_stop is None:
127
- ele_stop = len(self.line)
128
- if ele_start >= ele_stop:
129
- # we need an additional turn and space in the monitor for
130
- # the incomplete turn
131
- num_turns += 1
132
- _, monitor, _, _ = self.line.tracker._get_monitor(particles, True, num_turns)
133
- kwargs['turn_by_turn_monitor'] = monitor
134
-
135
- for ii in progress(
136
- range(0, num_turns, batch_size),
137
- desc='Tracking',
138
- unit_scale=scaling,
139
- ):
140
- one_turn_kwargs = kwargs.copy()
141
- is_first_batch = ii == 0
142
- is_last_batch = ii + batch_size >= num_turns
143
-
144
- if is_first_batch and is_last_batch:
145
- # This is the only batch, we track as normal
146
- pass
147
- elif is_first_batch:
148
- # Not the last batch, so track until the last element
149
- one_turn_kwargs['ele_stop'] = None
150
- one_turn_kwargs['num_turns'] = batch_size
151
- elif is_last_batch:
152
- # Not the first batch, so track from the first element
153
- one_turn_kwargs['ele_start'] = None
154
- remaining_turns = num_turns % batch_size
155
- if remaining_turns == 0:
156
- remaining_turns = batch_size
157
- one_turn_kwargs['num_turns'] = remaining_turns
158
- one_turn_kwargs['_reset_log'] = False
159
- elif not is_first_batch and not is_last_batch:
160
- # A 'middle batch', track from first to last element
161
- one_turn_kwargs['num_turns'] = batch_size
162
- one_turn_kwargs['ele_start'] = None
163
- one_turn_kwargs['ele_stop'] = None
164
- one_turn_kwargs['_reset_log'] = False
165
- self._tracking_func(particles, rf_shift_per_turn, **one_turn_kwargs)
166
- if not np.any(particles.state == 1):
167
- break
168
-
169
- else:
170
- self._tracking_func(particles, rf_shift_per_turn, num_turns=num_turns, *args, **kwargs)
171
-
172
- if not np.any(particles.state == 1):
173
- print(f"All particles lost at turn {particles.at_turn.max()}, stopped sweep at "
174
- + f"{self.current_sweep_value}Hz.")
175
-
176
- if time:
177
- t1 = perf_counter()
178
- self.line.tracker._context.synchronize()
179
- self.line.tracker.time_last_track = t1 - t0
138
+ if isinstance(self.cavities, str):
139
+ self.cavities = [self.cavities]
140
+ for cav in self.cavities:
141
+ if cav not in self.env.elements:
142
+ raise ValueError(f"Cavity `{cav}` not found in environment!")
143
+ if len(self.cavities) == 0:
144
+ raise ValueError("No cavities found in the line!")
145
+ freq = np.array([self.env[cav].frequency for cav in self.cavities])
146
+ volt = np.array([self.env[cav].voltage for cav in self.cavities])
147
+ lag = np.array([self.env[cav].lag for cav in self.cavities])
148
+ s_pos = []
149
+ name_first_in_line = []
150
+ for cav in self.cavities:
151
+ if cav in tt_c.name:
152
+ s_pos.append(tt_c.rows[cav].s_start[0])
153
+ name_first_in_line.append(cav)
154
+ elif cav in tt_c.parent_name:
155
+ s_pos.append(tt_c.rows[tt_c.parent_name == cav].s_start.min())
156
+ name_first_in_line.append(tt_c.rows[tt_c.parent_name == cav].name[0])
180
157
  else:
181
- self.line.tracker.time_last_track = None
182
-
183
-
184
- def reset(self):
185
- self.line['rf_sweep'].dzeta = 0
158
+ raise ValueError(f"Cavity `{cav}` not found in the line!")
159
+ idx = np.argsort(freq)
160
+ boundaries = np.where(~np.isclose(freq[idx][1:], freq[idx][:-1],
161
+ rtol=1e-8, atol=1e-12)
162
+ )[0] + 1
163
+ groups = []
164
+ for gidx in np.split(idx, boundaries):
165
+ groups.append({
166
+ 'names': self.cavities[gidx],
167
+ 'freq': np.mean(freq[gidx]),
168
+ 'voltage': volt[gidx].sum(),
169
+ 's_pos': np.array(s_pos)[gidx],
170
+ 'lag': lag[gidx],
171
+ 'name_first_in_line': np.array(name_first_in_line)[gidx],
172
+ })
173
+ self.cavities = sorted(groups, key=lambda g: (g['voltage'], g['freq']), reverse=True)
174
+ if np.isclose(self.cavities[0]['voltage'], 0):
175
+ raise ValueError("No active cavity found!")
176
+ self.f_RF = self.cavities[0]['freq']
177
+ self.phi = np.deg2rad(self.cavities[0]['lag'].mean())
178
+ self.V = self.cavities[0]['voltage']
179
+ self.L = self.line.get_length()
180
+ if len(self.cavities) > 1:
181
+ print("Found multiple cavities with different frequencies:")
182
+ for g in self.cavities:
183
+ print(f"{g['freq']}Hz at {g['voltage']}V: {g['names']}")
184
+ print(r"The sweep will be performed with respect to the highest "
185
+ + f"voltage cavity at {self.f_RF}Hz. The other cavities will "
186
+ + f"be shifted accordingly.")
186
187
 
187
188
 
188
- def _tracking_func(self, particles, rf_shift_per_turn, num_turns=1, *args, **kwargs):
189
- existing_sweep = self.current_sweep_value
190
- for i in range(num_turns):
191
- sweep = existing_sweep + i*rf_shift_per_turn
192
- self.line['rf_sweep'].dzeta = self.L * sweep / (self.f_RF + sweep)
193
- # for cav in cavities:
194
- # self.line[cav].frequency = freq + sweep
195
- self.line.track(particles, num_turns=1, *args, **kwargs)
196
- if not np.any(particles.state == 1):
197
- break
189
+ def _install_zeta_shift(self):
190
+ if 'rf_sweep' not in self.env.elements:
191
+ idx = np.argsort(self.cavities[0]['s_pos'])
192
+ first_cavity = self.cavities[0]['name_first_in_line'][idx[0]]
193
+ self.env.elements['rf_sweep'] = xt.ZetaShift(dzeta=0)
194
+ self.line.insert('rf_sweep', at=f'{first_cavity}@start')
@@ -1,15 +1,13 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: xcoll
3
- Version: 0.6.2
3
+ Version: 0.6.4
4
4
  Summary: Xsuite collimation package
5
- License: Apache 2.0
5
+ License: Apache-2.0
6
6
  Author: Frederik F. Van der Veken
7
7
  Author-email: frederik@cern.ch
8
- Requires-Python: >=3.8
9
- Classifier: License :: Other/Proprietary License
8
+ Requires-Python: >=3.10
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
10
  Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.8
12
- Classifier: Programming Language :: Python :: 3.9
13
11
  Classifier: Programming Language :: Python :: 3.10
14
12
  Classifier: Programming Language :: Python :: 3.11
15
13
  Classifier: Programming Language :: Python :: 3.12
@@ -17,13 +15,19 @@ Classifier: Programming Language :: Python :: 3.13
17
15
  Provides-Extra: tests
18
16
  Requires-Dist: numpy (>=1.0)
19
17
  Requires-Dist: pandas (>=1.4)
20
- Requires-Dist: ruamel-yaml (>=0.17.31,<0.18.0) ; extra == "tests"
21
- Requires-Dist: xdeps (>=0.10.5)
22
- Requires-Dist: xobjects (>=0.5.0)
23
- Requires-Dist: xpart (>=0.23.0)
24
- Requires-Dist: xtrack (>=0.84.8)
18
+ Requires-Dist: pytest ; extra == "tests"
19
+ Requires-Dist: pytest-html ; extra == "tests"
20
+ Requires-Dist: pytest-xdist ; extra == "tests"
21
+ Requires-Dist: ruamel-yaml (>=0.17.31,<0.18.15)
22
+ Requires-Dist: xdeps (>=0.10.6)
23
+ Requires-Dist: xobjects (>=0.5.2)
24
+ Requires-Dist: xpart (>=0.23.1)
25
+ Requires-Dist: xtrack (>=0.90.1)
26
+ Project-URL: Bug Tracker, https://github.com/xsuite/xsuite/issues
27
+ Project-URL: Documentation, https://xsuite.readthedocs.io/
25
28
  Project-URL: Homepage, https://github.com/xsuite/xcoll
26
29
  Project-URL: Repository, https://github.com/xsuite/xcoll
30
+ Project-URL: download, https://pypi.python.org/pypi/xcoll
27
31
  Description-Content-Type: text/markdown
28
32
 
29
33
  # xcoll
@@ -1,4 +1,4 @@
1
- xcoll/__init__.py,sha256=wEk3szUGeeN2Bg7_nx2D2pCgzRR0zcbEcWCP33p-e3I,854
1
+ xcoll/__init__.py,sha256=7qEja96thydS08Q1IVdLeeT3VslAZ1OQbGzXJ96euVE,872
2
2
  xcoll/beam_elements/__init__.py,sha256=qu2-LefWfEKZHfALGqZo97DTrwdZVh7Sp97V-3XokJU,1189
3
3
  xcoll/beam_elements/absorber.py,sha256=Gw1l1ng1MqF0dRTk7YhkiPAoinS5xsTASMxMDWGsmTw,2842
4
4
  xcoll/beam_elements/base.py,sha256=mjnzLbZ-GC56N56Eq5r5oQB8cLmeaqR5oEH1-FnS_H4,57816
@@ -10,13 +10,16 @@ xcoll/beam_elements/elements_src/emittance_monitor.h,sha256=vlHzQFoUjKQHWBmzpaSz
10
10
  xcoll/beam_elements/elements_src/everest_block.h,sha256=ITSzfiqwm8ZNIkAj_odQkAjKhPcdT8b0AUlq_uxtsqI,6562
11
11
  xcoll/beam_elements/elements_src/everest_collimator.h,sha256=fkD5GazVv2zlmqyb6s9zVNMq6baXeFb_pf7gg9TKjNc,9787
12
12
  xcoll/beam_elements/elements_src/everest_crystal.h,sha256=LISp_9NEWMIi5GvZ3LwPfeSbmsbXvHWcTqxW6eCCsiE,11951
13
+ xcoll/beam_elements/elements_src/rf_sweep.h,sha256=eTPPSJvFrkoh9STI0hmmiozwMUL-TQVhz1mOZQhObWE,846
13
14
  xcoll/beam_elements/elements_src/transparent_collimator.h,sha256=pA_Fxx85N87iSbpHSjR2OSOx6JN9e38T1pOUKrC7zxs,4610
14
15
  xcoll/beam_elements/elements_src/transparent_crystal.h,sha256=DGX4uL0hpm4njOypoPuEWtMzYxnL9jQkf2ZrGaS0alI,4128
15
16
  xcoll/beam_elements/everest.py,sha256=iJva_S0OQnmG-qj7rIAiUCssu5WL_Qs5P_n6Qx-IWzo,9080
16
17
  xcoll/beam_elements/monitor.py,sha256=baMYT_PNya8KX35ReeMwk5Cm04ePUqiDF_s69L5GTX0,16968
18
+ xcoll/beam_elements/sweep.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
19
  xcoll/beam_elements/transparent.py,sha256=AZOWfH3dvsetL6DjQGejUgX7T18e_3omIIffG_1gwc0,2894
18
20
  xcoll/colldb.py,sha256=WaJC6gkDNVvxo65OhucTM6Fwo6pgRFHNnBnHSkiX7AQ,31054
19
- xcoll/general.py,sha256=tayWZwdCHAmngxUu5-_6CV_PDpnIdLJlzXrtbGZfkOA,534
21
+ xcoll/general.py,sha256=sIcxR8vmoZcCI073Kwty4Zal-6045GpLYpTCRkdG_dA,534
22
+ xcoll/geometry.md,sha256=AARDOk5lZWFBAllX75UYMRywSYSB04FIlYWE0ra1t5c,1623
20
23
  xcoll/headers/checks.h,sha256=qdXsOTBOK1MwW6bdFF93j4yE648mcDtEv5rGN1w9sfk,1582
21
24
  xcoll/headers/particle_states.py,sha256=N8ehLtg99358I4RGCJ3sjuKCk2LVdGqgVx2xGoHrRdM,1959
22
25
  xcoll/initial_distribution.py,sha256=CHhqeCVjVOyaBWhfy2sDgLwIgtXZoqcTW-su-M2YByE,10989
@@ -27,7 +30,10 @@ xcoll/interaction_record/interaction_types.py,sha256=XTeg2dcImMpqhTqzkJKh6JYam2v
27
30
  xcoll/line_tools.py,sha256=JBySkKKZ-RGumqAZF_8PSQ3OV0M87P78NeQgbXAdFc4,16699
28
31
  xcoll/lossmap.py,sha256=HLdhej9tUjk36T5BulVWurJtfiNa61L_1X7-8kT6JoQ,28407
29
32
  xcoll/plot.py,sha256=27fYdXstPg3o8XyeBlPuD2yz0GR3dKkNWy4kO2BD9WA,4071
30
- xcoll/rf_sweep.py,sha256=hMgW15uTp7qPprdlHCZBjOOe8Emdm-R0TfxPDoRXnJU,9021
33
+ xcoll/prebuild_kernels/__init__.py,sha256=HITO-StW6e3GujTvLzEFz2Y8bMDGnavVttwixVPgA-M,286
34
+ xcoll/prebuild_kernels/element_inits.py,sha256=9Qm34JXN7F08inWzXP6g6DU57ypRbyqHYwPK9Oc9BC4,219
35
+ xcoll/prebuild_kernels/elements.py,sha256=7P5cxZgjfeNmUNuDer372KgtjmhH39Kk1wReyKMhqig,456
36
+ xcoll/rf_sweep.py,sha256=_astbQSE7kr5AbnxOFR3WhduTvhkM6NR26EqyPMQ9EQ,9508
31
37
  xcoll/scattering_routines/engine.py,sha256=1VCBEZLMd5orFo3sZqK51NrqbqELBVrbsz6bB2SXsFQ,22962
32
38
  xcoll/scattering_routines/environment.py,sha256=xZ8A7XfvSfpe8vYbM5oD5qbcp8Tuag5qWAI6VqgGUlA,12033
33
39
  xcoll/scattering_routines/everest/__init__.py,sha256=7lkkeZ1liBjXVHCuRpgzZI6ohzHVMj5uJBO792147XY,286
@@ -54,8 +60,9 @@ xcoll/scattering_routines/geometry/rotation.h,sha256=lO3RaQBys9r0ROMjR8T8Rr7UsIE
54
60
  xcoll/scattering_routines/geometry/segments.h,sha256=7nKnnin2ByxkKyaYwGvFaqgLQg5uBba4CdLHL7L3iQs,7667
55
61
  xcoll/scattering_routines/geometry/sort.h,sha256=b1MkFO2ddzv1fWGeQzsLuz46qo2pKyRSXHjoAEVU7Ts,5763
56
62
  xcoll/xaux.py,sha256=mh4E_jhaUFm2LOKawJ0b6X4zuz8JiJhx6w7GcnRgIXQ,2291
57
- xcoll-0.6.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
58
- xcoll-0.6.2.dist-info/METADATA,sha256=3ggN0J33OYQp2Yjn7kWMTLeXmuTjI06lbAAJVWYkt7U,2739
59
- xcoll-0.6.2.dist-info/NOTICE,sha256=6DO_E7WCdRKc42vUoVVBPGttvQi4mRt9fAcxj9u8zy8,74
60
- xcoll-0.6.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
61
- xcoll-0.6.2.dist-info/RECORD,,
63
+ xcoll-0.6.4.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
64
+ xcoll-0.6.4.dist-info/METADATA,sha256=VGOnACo61c0JgUQ6i3330JW2bLlWFxB04xlQEyGHp2M,2953
65
+ xcoll-0.6.4.dist-info/NOTICE,sha256=6DO_E7WCdRKc42vUoVVBPGttvQi4mRt9fAcxj9u8zy8,74
66
+ xcoll-0.6.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
67
+ xcoll-0.6.4.dist-info/entry_points.txt,sha256=fC9oojAU6WjKujnGBodo7ZcEeBGfSfeLPO5287echdY,26
68
+ xcoll-0.6.4.dist-info/RECORD,,
@@ -0,0 +1,3 @@
1
+ [xobjects]
2
+ include=xcoll
3
+
File without changes
File without changes
File without changes