Skip to content

Commit 313c41b

Browse files
authored
Merge pull request #154 from xsuite/release/v0.6.4
Release 0.6.4
2 parents 89913bb + 2986950 commit 313c41b

File tree

10 files changed

+254
-70
lines changed

10 files changed

+254
-70
lines changed

examples/lhc_run3_lossmap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,5 @@
9494

9595
print(f"Total calculation time {time.time()-start_time}s")
9696

97-
ThisLM.plot()
97+
ThisLM.plot(savefig=Path(path_out, f'lossmap_B{beam}{plane}.pdf'))
9898
plt.show()

examples/lhc_run3_lossmap_with_blowup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@
115115

116116
print(f"Total calculation time {time.time()-start_time}s")
117117

118-
ThisLM.plot()
118+
ThisLM.plot(savefig=Path(path_out, f'lossmap_B{beam}{plane}.pdf'))
119119
plt.show()
120120

121121

examples/lhc_run3_lossmap_with_crystals.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,5 +141,5 @@
141141

142142
print(f"Total calculation time {time.time()-start_time}s")
143143

144-
ThisLM.plot()
144+
ThisLM.plot(savefig=Path(path_out, f'lossmap_B{beam}{plane}.pdf'))
145145
plt.show()

examples/lhc_run3_offmomentum_lossmap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,5 @@
140140

141141
print(f"Total calculation time {time.time()-start_time}s")
142142

143-
ThisLM.plot()
143+
ThisLM.plot(savefig=Path(path_out, f'lossmap_B{beam}{plane}.pdf'))
144144
plt.show()

examples/scatter.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import time
2+
import numpy as np
3+
import pandas as pd
4+
from pathlib import Path
5+
import matplotlib.pyplot as plt
6+
import matplotlib.colors as mcolors
7+
8+
import xobjects as xo
9+
import xpart as xp
10+
import xtrack as xt
11+
import xcoll as xc
12+
13+
14+
num_part = 100000
15+
_capacity = 2*num_part
16+
particle_ref = xp.Particles.reference_from_pdg_id(pdg_id='proton', p0c=7e12)
17+
18+
everest_coll = xc.EverestCollimator(length=1.0, material=xc.materials.MolybdenumGraphite, jaw=[0.01, -0.01])
19+
20+
fluka_coll = xc.FlukaCollimator(length=1.0, jaw=[0.01, -0.01])
21+
xc.FlukaEngine.start(elements=fluka_coll, names='tcp.c6l7.b1', debug_level=1, _capacity=_capacity, cwd='temp_scratch')
22+
xc.FlukaEngine.set_particle_ref(particle_ref=particle_ref)
23+
24+
# g4_coll = xc.Geant4Collimator(length=1.0, material='mogr', jaw=[0.1, -0.1], geant4_id='g4_coll')
25+
26+
27+
# Plotting function
28+
# -----------------
29+
30+
dri = xt.Drift(length=everest_coll.length)
31+
def plot_scatters(part_init, part, outfile, show_colorbar=True):
32+
devmin = 1e-6
33+
devmax = 1
34+
part_dri = part_init.copy()
35+
dri.track(part_dri)
36+
part_dri.sort(interleave_lost_particles=True)
37+
part.sort(interleave_lost_particles=True)
38+
mask = part.state > 0
39+
dev = 1.e3*np.sqrt((part.x[mask] - part_dri.x[part.parent_particle_id[mask]])**2
40+
+ (part.y[mask] - part_dri.y[part.parent_particle_id[mask]])**2)
41+
dev[dev<devmin] = devmin
42+
if len(dev[dev>devmax]) > 0:
43+
print(f'Warning: {len(dev[dev>devmax])} particles have deviation > {devmax} mm')
44+
45+
if show_colorbar:
46+
fig = plt.figure(figsize=(7.11, 3.5))
47+
else:
48+
fig = plt.figure(figsize=(6, 3.5))
49+
plt.scatter(1.e3*part_init.x[part.parent_particle_id[mask]],
50+
1.e3*part_init.y[part.parent_particle_id[mask]],
51+
c=dev, s=0.25, cmap='viridis',norm=mcolors.LogNorm(vmin=devmin, vmax=devmax))
52+
plt.vlines(10, -5, 5, colors='r')
53+
plt.xlim(8.5, 11.5)
54+
plt.ylim(-5, 5)
55+
plt.xlabel('x [mm]')
56+
plt.ylabel('y [mm]')
57+
if show_colorbar:
58+
plt.colorbar(label='Deviation from drift [mm]')
59+
plt.tight_layout()
60+
plt.savefig(outfile, dpi=300)
61+
62+
63+
# Generate particles
64+
# ------------------
65+
66+
y = np.random.normal(loc=0, scale=1e-3, size=num_part)
67+
py = np.random.normal(loc=0, scale=1e-3, size=num_part)
68+
delta = np.random.normal(loc=0, scale=3e-4, size=num_part)
69+
70+
part_init = []
71+
x0 = 9.25e-3
72+
x = np.random.normal(loc=x0, scale=1e-4, size=num_part)
73+
part_init.append(xp.build_particles(particle_ref=particle_ref, x=x, px=0, y=y, py=py, delta=delta, _capacity=_capacity))
74+
75+
x0 = 0.01
76+
x = np.random.normal(loc=x0, scale=1e-4, size=num_part)
77+
part_init.append(xp.build_particles(particle_ref=particle_ref, x=x, px=0, y=y, py=py, delta=delta, _capacity=_capacity))
78+
79+
x0 = 0.01075
80+
x = np.random.normal(loc=x0, scale=1e-4, size=num_part)
81+
part_init.append(xp.build_particles(particle_ref=particle_ref, x=x, px=0, y=y, py=py, delta=delta, _capacity=_capacity))
82+
83+
84+
# Fluka
85+
# -----
86+
87+
part_fluka = []
88+
for this_part_init in part_init:
89+
this_part = this_part_init.copy()
90+
t_start = time.time()
91+
fluka_coll.track(this_part)
92+
t_end = time.time()
93+
94+
print(f"FLUKA execution time: {t_end - t_start} s")
95+
print(f"Survived in FLUKA: {len(np.unique(this_part.parent_particle_id[this_part.state>0]))}/{num_part}")
96+
this_part.sort(interleave_lost_particles=True)
97+
part_fluka.append(this_part)
98+
99+
xc.FlukaEngine.stop()
100+
101+
for idx in range(3):
102+
plot_scatters(part_init[idx], part_fluka[idx], f'fluka_collimator_{idx}.png', show_colorbar=True)
103+
104+
105+
# Everest
106+
# -------
107+
108+
# Pre-run for compilation
109+
this_part = part_init[0].copy()
110+
everest_coll.track(this_part)
111+
112+
part_everest = []
113+
for this_part_init in part_init:
114+
this_part = this_part_init.copy()
115+
t_start = time.time()
116+
everest_coll.track(this_part)
117+
t_end = time.time()
118+
119+
print(f"Everest execution time: {t_end - t_start} s")
120+
print(f"Survived in Everest: {len(np.unique(this_part.parent_particle_id[this_part.state>0]))}/{num_part}")
121+
this_part.sort(interleave_lost_particles=True)
122+
part_everest.append(this_part)
123+
124+
for idx in range(3):
125+
plot_scatters(part_init[idx], part_everest[idx], f'everest_collimator_{idx}.png', show_colorbar=True)
126+
127+
128+
# # Geant4
129+
# # ------
130+
131+
# xc.Geant4Engine.start(elements=[g4_coll], seed=1993, bdsim_config_file='settings_protons.gmad', particle_ref=particle_ref)
132+
133+
# part_g4 = []
134+
# for this_part_init in part_init:
135+
# this_part = this_part_init.copy()
136+
# t_start = time.time()
137+
# g4_coll.track(this_part)
138+
# t_end = time.time()
139+
140+
# print(f"Geant4 execution time: {t_end - t_start} s")
141+
# print(f"Survived in Geant4: {len(np.unique(this_part.parent_particle_id[this_part.state>0]))}/{num_part}")
142+
# this_part.sort(interleave_lost_particles=True)
143+
# part_g4.append(this_part)
144+
145+
# xc.Geant4Engine.stop()
146+
147+
# for idx in range(3):
148+
# plot_scatters(part_init[idx], part_g4[idx], f'g4_collimator_{idx}.png', show_colorbar=True)

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "xcoll"
3-
version = "0.6.3"
3+
version = "0.6.4"
44
description = "Xsuite collimation package"
55
authors = [
66
{name="Frederik F. Van der Veken", email="[email protected]"},
@@ -25,7 +25,7 @@ dependencies = [
2525
"xobjects>=0.5.2",
2626
"xdeps>=0.10.6",
2727
"xpart>=0.23.1",
28-
"xtrack>=0.89.3",
28+
"xtrack>=0.90.1",
2929
]
3030

3131
[project.optional-dependencies]
@@ -46,7 +46,7 @@ exclude = ["xcoll/lib", "xcoll/config"]
4646

4747
[poetry.group.dev.dependencies]
4848
pytest = ">=7.3"
49-
xaux = ">=0.3.5"
49+
xaux = ">=0.3.6"
5050

5151
[build-system]
5252
# Needed for pip install -e (BTW: need pip version 22)

tests/test_rf_sweep.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@
33
# Copyright (c) CERN, 2024. #
44
# ######################################### #
55

6-
from pathlib import Path
76
import numpy as np
87
import pytest
98

109
import xtrack as xt
1110
import xcoll as xc
1211
from xobjects.test_helpers import for_all_test_contexts
1312

14-
path = Path(__file__).parent / 'data'
13+
path = xc._pkg_root.parent / 'tests' / 'data'
1514

1615
@for_all_test_contexts
1716
@pytest.mark.parametrize("sweep, beam", [[-300, 1], [300, 2], [3500, 3]],
@@ -20,27 +19,52 @@ def test_rf_sweep(sweep, beam, test_context):
2019
num_turns = 6000
2120
num_particles = 5
2221
if beam == 3:
22+
bh = 3.5e-3
23+
sweep *= 25
2324
line = xt.load(path / f'sequence_sps_q20_inj.json')['sps']
24-
line.insert('markkk', xt.Marker(), at=2822)
25+
line.insert('cavity_mid', xt.Marker(), at=2822) # Inside thick cavity as to slice it
2526
tt_c = line.get_table().rows['ac.*']
2627
assert 'ThickSliceCavity' in tt_c.element_type
2728
else:
29+
bh = 3.e-4
2830
line = xt.load(path / f'sequence_lhc_run3_b{beam}.json')
2931

30-
line.build_tracker()
32+
line.build_tracker(_context=test_context)
3133

32-
part = line.build_particles(delta=np.linspace(-2e-4, 2e-4, num_particles),
33-
x_norm=0, px_norm=0, y_norm=0, py_norm=0)
34+
part = line.build_particles(delta=np.linspace(-0.7*bh, 0.7*bh, num_particles),
35+
x_norm=0, px_norm=0, y_norm=0, py_norm=0, _context=test_context)
3436

3537
rf_sweep = xc.RFSweep(line)
3638
rf_sweep.prepare(sweep_per_turn=sweep/num_turns)
3739
rf_sweep.info()
38-
# This sweep is 3.5 buckets, so check that all particles are at least 3 buckets away
3940
line.track(particles=part, num_turns=num_turns)
4041

42+
# This sweep is 3.5 buckets, so check that all particles are at least 3 buckets away
4143
# negative sweep => positive off-momentum etc
4244
if sweep < 0:
43-
assert np.all(part.delta > 1.5e-3)
45+
assert np.all(part.delta > 3*bh)
4446
else:
45-
assert np.all(part.delta < -1.5e-3)
47+
assert np.all(part.delta < -3*bh)
48+
49+
50+
def test_rf_sweep_old_style():
51+
num_turns = 6000
52+
num_particles = 5
53+
line = xt.load(path / f'sequence_lhc_run3_b2.json')
4654

55+
line.build_tracker()
56+
57+
part = line.build_particles(delta=np.linspace(-2e-4, 2e-4, num_particles),
58+
x_norm=0, px_norm=0, y_norm=0, py_norm=0)
59+
60+
sweep = -300
61+
rf_sweep = xc.RFSweep(line)
62+
with pytest.warns(DeprecationWarning, match="The `sweep` argument is deprecated."):
63+
with pytest.warns(DeprecationWarning, match="The `num_turns` argument is deprecated."):
64+
rf_sweep.info(sweep=sweep, num_turns=num_turns)
65+
with pytest.warns(DeprecationWarning):
66+
rf_sweep.track(sweep=sweep, num_turns=num_turns, particles=part)
67+
68+
# This sweep is 3.5 buckets, so check that all particles are at least 3 buckets away
69+
# negative sweep => positive off-momentum etc
70+
assert np.all(part.delta > 1.5e-3)

tests/test_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
from xcoll import __version__
77

88
def test_version():
9-
assert __version__ == '0.6.3'
9+
assert __version__ == '0.6.4'

xcoll/general.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@
1212
# ======================
1313
# Do not change
1414
# ======================
15-
__version__ = '0.6.3'
15+
__version__ = '0.6.4'
1616
# ======================

0 commit comments

Comments
 (0)