xcoll 0.5.9__py3-none-any.whl → 0.5.11__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/beam_elements/base.py +40 -9
- xcoll/colldb.py +164 -176
- xcoll/general.py +1 -1
- xcoll/initial_distribution.py +8 -2
- xcoll/line_tools.py +6 -6
- {xcoll-0.5.9.dist-info → xcoll-0.5.11.dist-info}/METADATA +4 -4
- {xcoll-0.5.9.dist-info → xcoll-0.5.11.dist-info}/RECORD +10 -13
- xcoll/beam_elements/__init__.py.orig +0 -32
- xcoll/colldb.py.orig +0 -654
- xcoll/initial_distribution.py.orig +0 -224
- {xcoll-0.5.9.dist-info → xcoll-0.5.11.dist-info}/LICENSE +0 -0
- {xcoll-0.5.9.dist-info → xcoll-0.5.11.dist-info}/NOTICE +0 -0
- {xcoll-0.5.9.dist-info → xcoll-0.5.11.dist-info}/WHEEL +0 -0
xcoll/beam_elements/base.py
CHANGED
|
@@ -12,8 +12,8 @@ from ..interaction_record import InteractionRecord
|
|
|
12
12
|
from ..general import _pkg_root
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
OPEN_JAW = 3
|
|
16
|
-
OPEN_GAP = 999
|
|
15
|
+
OPEN_JAW = 3
|
|
16
|
+
OPEN_GAP = 999
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class InvalidXcoll(xt.BeamElement):
|
|
@@ -198,6 +198,10 @@ class BaseCollimator(BaseBlock):
|
|
|
198
198
|
to_assign['angle_L'] = kwargs.pop('angle_L', 0)
|
|
199
199
|
to_assign['angle_R'] = kwargs.pop('angle_R', 0)
|
|
200
200
|
|
|
201
|
+
# We do not allow any combination of jaw_ and gap_ attributes
|
|
202
|
+
# (except when jaw=..., gap=None or jaw=None, gap=... is used, as this is how the colldb installs it)
|
|
203
|
+
kwargs = {kk: vv for kk, vv in kwargs.items() if not vv is None}
|
|
204
|
+
|
|
201
205
|
# Set jaw
|
|
202
206
|
if 'jaw' in kwargs:
|
|
203
207
|
for key in ['jaw_L', 'jaw_R', 'jaw_LU', 'jaw_LD', 'jaw_RU', 'jaw_RD', 'gap', 'gap_L', 'gap_R']:
|
|
@@ -333,7 +337,7 @@ class BaseCollimator(BaseBlock):
|
|
|
333
337
|
or (self.tilt_L == 0 and self.tilt_R == 0):
|
|
334
338
|
return [self.jaw_L, self.jaw_R]
|
|
335
339
|
else:
|
|
336
|
-
return [[self.jaw_LU, self.
|
|
340
|
+
return [[self.jaw_LU, self.jaw_LD], [self.jaw_RU, self.jaw_RD]]
|
|
337
341
|
|
|
338
342
|
@jaw.setter # Keeps the tilts unless all 4 corners are specified
|
|
339
343
|
def jaw(self, val):
|
|
@@ -352,8 +356,8 @@ class BaseCollimator(BaseBlock):
|
|
|
352
356
|
if hasattr(val[0], '__iter__'):
|
|
353
357
|
if hasattr(val[1], '__iter__') and len(val[0]) == 2 and len(val[1]) == 2:
|
|
354
358
|
self.jaw_LU = val[0][0]
|
|
355
|
-
self.
|
|
356
|
-
self.
|
|
359
|
+
self.jaw_LD = val[0][1]
|
|
360
|
+
self.jaw_RU = val[1][0]
|
|
357
361
|
self.jaw_RD = val[1][1]
|
|
358
362
|
return
|
|
359
363
|
else:
|
|
@@ -556,6 +560,8 @@ class BaseCollimator(BaseBlock):
|
|
|
556
560
|
print("Warning: Setting a tilt does not preserve the hierarchy, as there "
|
|
557
561
|
+ "will always be one corner that tightens (the tilt is applied at "
|
|
558
562
|
+ "the centre of the jaw).")
|
|
563
|
+
if val > np.pi/2 or val < -np.pi/2:
|
|
564
|
+
raise ValueError("Tilts larger than 90 degrees are not supported.")
|
|
559
565
|
self._sin_yL = np.sin(val)
|
|
560
566
|
self._cos_yL = np.cos(val)
|
|
561
567
|
self._tan_yL = np.tan(val)
|
|
@@ -577,6 +583,8 @@ class BaseCollimator(BaseBlock):
|
|
|
577
583
|
print("Warning: Setting a tilt does not preserve the hierarchy, as there "
|
|
578
584
|
+ "will always be one corner that tightens (the tilt is applied at "
|
|
579
585
|
+ "the centre of the jaw).")
|
|
586
|
+
if val > np.pi/2 or val < -np.pi/2:
|
|
587
|
+
raise ValueError("Tilts larger than 90 degrees are not supported.")
|
|
580
588
|
self._sin_yR = np.sin(val)
|
|
581
589
|
self._cos_yR = np.cos(val)
|
|
582
590
|
self._tan_yR = np.tan(val)
|
|
@@ -651,6 +659,11 @@ class BaseCollimator(BaseBlock):
|
|
|
651
659
|
self._nemitt_x = val
|
|
652
660
|
self._apply_optics()
|
|
653
661
|
|
|
662
|
+
@property
|
|
663
|
+
def gemitt_x(self):
|
|
664
|
+
if self.nemitt_x is not None and self.optics_ready():
|
|
665
|
+
return self.nemitt_x / self.optics['beta_gamma_rel']
|
|
666
|
+
|
|
654
667
|
@property
|
|
655
668
|
def nemitt_y(self):
|
|
656
669
|
if self._nemitt_y == 0:
|
|
@@ -666,6 +679,11 @@ class BaseCollimator(BaseBlock):
|
|
|
666
679
|
self._nemitt_y = val
|
|
667
680
|
self._apply_optics()
|
|
668
681
|
|
|
682
|
+
@property
|
|
683
|
+
def gemitt_y(self):
|
|
684
|
+
if self.nemitt_y is not None and self.optics_ready():
|
|
685
|
+
return self.nemitt_y / self.optics['beta_gamma_rel']
|
|
686
|
+
|
|
669
687
|
@property
|
|
670
688
|
def emittance(self):
|
|
671
689
|
if self.nemitt_x is not None and self.nemitt_y is not None:
|
|
@@ -726,8 +744,8 @@ class BaseCollimator(BaseBlock):
|
|
|
726
744
|
alfy = self.optics[self.align]['alfy'][0]
|
|
727
745
|
betx = self.optics[self.align]['betx'][0]
|
|
728
746
|
bety = self.optics[self.align]['bety'][0]
|
|
729
|
-
divx = -np.sqrt(self.
|
|
730
|
-
divy = -np.sqrt(self.
|
|
747
|
+
divx = -np.sqrt(self.gemitt_x/betx)*alfx
|
|
748
|
+
divy = -np.sqrt(self.gemitt_y/bety)*alfy
|
|
731
749
|
if hasattr(self, '_cos_zL'):
|
|
732
750
|
if self.side != 'right':
|
|
733
751
|
return divx if abs(self.angle_L) < 1e-6 else divy
|
|
@@ -965,8 +983,6 @@ class BaseCollimator(BaseBlock):
|
|
|
965
983
|
assert self._jaws_parallel == False
|
|
966
984
|
assert np.isclose(self._sin_zDiff, self._cos_zL*self._sin_zR - self._sin_zL*self._cos_zR)
|
|
967
985
|
assert np.isclose(self._cos_zDiff, self._cos_zL*self._cos_zR + self._sin_zL*self._sin_zR)
|
|
968
|
-
if self.side == 'both' and abs(self.tilt_L - self.tilt_R) >= 90.:
|
|
969
|
-
raise ValueError("Tilts of both jaws differ more than 90 degrees!")
|
|
970
986
|
if self.side != 'right':
|
|
971
987
|
ang = abs(np.arccos(self._cos_yL))
|
|
972
988
|
ang = np.pi - ang if ang > np.pi/2 else ang
|
|
@@ -1058,6 +1074,11 @@ class BaseCrystal(BaseBlock):
|
|
|
1058
1074
|
# Set angle
|
|
1059
1075
|
to_assign['angle'] = kwargs.pop('angle', 0)
|
|
1060
1076
|
|
|
1077
|
+
# We do not allow any combination of jaw_ and gap_ attributes
|
|
1078
|
+
# (except when jaw=..., gap=None or jaw=None, gap=... is used, as this is how the colldb installs it)
|
|
1079
|
+
kwargs = {kk: vv for kk, vv in kwargs.items() if not vv is None}
|
|
1080
|
+
|
|
1081
|
+
|
|
1061
1082
|
# Set jaw
|
|
1062
1083
|
if 'jaw' in kwargs:
|
|
1063
1084
|
for key in ['jaw_U', 'jaw_D', 'gap']:
|
|
@@ -1214,6 +1235,8 @@ class BaseCrystal(BaseBlock):
|
|
|
1214
1235
|
if val > min(0, -self.bending_angle/2):
|
|
1215
1236
|
print("Warning: Setting a positive tilt does not preserve the hierarchy, as the "
|
|
1216
1237
|
+ "crystal tightens towards the beam.")
|
|
1238
|
+
if val > np.pi/2 or val < -np.pi/2:
|
|
1239
|
+
raise ValueError("Tilts larger than 90 degrees are not supported.")
|
|
1217
1240
|
self._sin_y = np.sin(val)
|
|
1218
1241
|
self._cos_y = np.cos(val)
|
|
1219
1242
|
self._tan_y = np.tan(val)
|
|
@@ -1243,6 +1266,10 @@ class BaseCrystal(BaseBlock):
|
|
|
1243
1266
|
def nemitt_x(self, val):
|
|
1244
1267
|
BaseCollimator.nemitt_x.fset(self, val)
|
|
1245
1268
|
|
|
1269
|
+
@property
|
|
1270
|
+
def gemitt_x(self):
|
|
1271
|
+
return BaseCollimator.gemitt_x.fget(self)
|
|
1272
|
+
|
|
1246
1273
|
@property
|
|
1247
1274
|
def nemitt_y(self):
|
|
1248
1275
|
return BaseCollimator.nemitt_y.fget(self)
|
|
@@ -1251,6 +1278,10 @@ class BaseCrystal(BaseBlock):
|
|
|
1251
1278
|
def nemitt_y(self, val):
|
|
1252
1279
|
BaseCollimator.nemitt_y.fset(self, val)
|
|
1253
1280
|
|
|
1281
|
+
@property
|
|
1282
|
+
def gemitt_y(self):
|
|
1283
|
+
return BaseCollimator.gemitt_y.fget(self)
|
|
1284
|
+
|
|
1254
1285
|
@property
|
|
1255
1286
|
def emittance(self):
|
|
1256
1287
|
return BaseCollimator.emittance.fget(self)
|
xcoll/colldb.py
CHANGED
|
@@ -358,156 +358,158 @@ class CollimatorDatabase:
|
|
|
358
358
|
return pd.DataFrame(self._collimator_dict).transpose()
|
|
359
359
|
|
|
360
360
|
def to_yaml(self, out, lhc_style=True):
|
|
361
|
-
""
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
#
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
#
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
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
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
361
|
+
raise NotImplementedError("This functionality needs to be updated to be compatible with tilts and read "
|
|
362
|
+
+ "the families from the colldb instead of hard-coding them!")
|
|
363
|
+
# """
|
|
364
|
+
# Writes a colldb in memory to disk in the yaml format.
|
|
365
|
+
|
|
366
|
+
# > colldb_object.write_to_yaml(<path+name>, lhc_style=Bool)
|
|
367
|
+
|
|
368
|
+
# if lhc_style == True, it will add comments assuming that the collimators are named
|
|
369
|
+
# as in the lhc.
|
|
370
|
+
|
|
371
|
+
# The function can dump b1, b2 and a general bx, however multi-beam functionality is not yet
|
|
372
|
+
# added to the collmanager. TODO
|
|
373
|
+
|
|
374
|
+
# If any of the dumped keys contains capital letters (e.g. gap_L), it will not be possible
|
|
375
|
+
# to load it back into xcoll, since all keys are set to lowercase when importing TODO
|
|
376
|
+
# """
|
|
377
|
+
# # Dumps collimator database to a YAML file with optional LHC style formatting
|
|
378
|
+
# import re
|
|
379
|
+
|
|
380
|
+
# # Local helper functions
|
|
381
|
+
# def _format_dict_entry(key, value, spacing='', mapping=False, key_width=15):
|
|
382
|
+
# # Formats a dictionary entry into a string for YAML output
|
|
383
|
+
# formatted_values = ', '.join(f"{k}: {v}" for k, v in value.items())
|
|
384
|
+
# formatted_values = re.sub(r'none', 'null', formatted_values, flags=re.IGNORECASE)
|
|
385
|
+
# # Ensure key has a fixed width for alignment
|
|
386
|
+
# if mapping:
|
|
387
|
+
# formatted_key = f'{key}'.ljust(key_width)
|
|
388
|
+
# else:
|
|
389
|
+
# formatted_key = f'{key}:'.ljust(key_width)
|
|
390
|
+
# #formatted_values = formatted_values.ljust(key_width)
|
|
391
|
+
# return f"{spacing}{formatted_key} {{ {formatted_values} }}\n"
|
|
392
|
+
|
|
393
|
+
# def _print_values(keys, dct, file, spacing='', mapping=False):
|
|
394
|
+
# # Writes formatted dictionary entries to a file
|
|
395
|
+
# for key in keys:
|
|
396
|
+
# file.write(_format_dict_entry(key, dct[key], spacing=spacing, mapping=mapping))
|
|
397
|
+
|
|
398
|
+
# def _print_colls(colls, dcts, beam, file):
|
|
399
|
+
# # Filters and formats collimator data, then writes to a file
|
|
400
|
+
# coll_items_to_print = ['<<','gap','angle','material','active','length','side']
|
|
401
|
+
# file.write(f' {beam}:\n')
|
|
402
|
+
# for coll in colls:
|
|
403
|
+
# coll_dict = dcts.to_pandas().transpose().to_dict()[coll]
|
|
404
|
+
# fam = coll_dict['family']
|
|
405
|
+
# fam_keys = []
|
|
406
|
+
# if fam is not None:
|
|
407
|
+
# fam_keys = dcts._family_dict[fam].keys()
|
|
408
|
+
# coll_dict = {**{'<<': '*'+fam}, **coll_dict}
|
|
409
|
+
# temp_items_to_print = []
|
|
410
|
+
# if coll_dict['crystal'] and str(coll_dict['crystal'])!='nan':
|
|
411
|
+
# temp_items_to_print = ['bending_radius','width','height','miscut','crystal']
|
|
412
|
+
# # if 'angle_L' in coll_dict and coll_dict['angle_L'] == coll_dict['angle_R']:
|
|
413
|
+
# # coll_dict.update({'angle': coll_dict['angle_L']})
|
|
414
|
+
# # else:
|
|
415
|
+
# # temp_items_to_print = temp_items_to_print + ['angle_L','angle_R']
|
|
416
|
+
# # if coll_dict['gap_L'] == coll_dict['gap_R']:
|
|
417
|
+
# # coll_dict.update({'gap': coll_dict['gap_L']})
|
|
418
|
+
# # elif coll_dict['gap_L'] is None and coll_dict['gap_R'] is not None:
|
|
419
|
+
# # coll_dict.update({'gap': coll_dict['gap_R']})
|
|
420
|
+
# # elif coll_dict['gap_L'] is not None and coll_dict['gap_R'] is None:
|
|
421
|
+
# # coll_dict.update({'gap': coll_dict['gap_L']})
|
|
422
|
+
# # else:
|
|
423
|
+
# # temp_items_to_print = temp_items_to_print + ['gap_L','gap_R']
|
|
424
|
+
# value = {}
|
|
425
|
+
# overwritten_keys = coll_dict['overwritten_keys']
|
|
426
|
+
# for key, val in coll_dict.items():
|
|
427
|
+
# if key == 'active_length':
|
|
428
|
+
# key = 'length'
|
|
429
|
+
# if (key in coll_items_to_print+temp_items_to_print) and (key not in (set(fam_keys)-set(overwritten_keys))) and (val != 'both'):
|
|
430
|
+
# value.update({key: val})
|
|
431
|
+
# file.write(_format_dict_entry(coll, value, spacing=' '))
|
|
432
|
+
# file.write('\n')
|
|
433
|
+
|
|
434
|
+
# 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']
|
|
435
|
+
# with open(f'{out}.yaml', 'w') as file:
|
|
436
|
+
# if '_family_dict' in self.__dict__.keys():
|
|
437
|
+
# file.write('families:\n')
|
|
438
|
+
# if lhc_style:
|
|
439
|
+
# printed_families = []
|
|
440
|
+
# fams_in_dict = self._family_dict.keys()
|
|
441
|
+
|
|
442
|
+
# # Momentum cleaning
|
|
443
|
+
# file.write(' # Momentum cleaning\n')
|
|
444
|
+
# sel_fam = [fam for fam in LHC_families if re.match('.*3', fam) and (fam in fams_in_dict)]
|
|
445
|
+
# printed_families += sel_fam
|
|
446
|
+
# _print_values(sel_fam, self._family_dict, file, spacing=' - &', mapping=True)
|
|
447
|
+
|
|
448
|
+
# # Betatron cleaning
|
|
449
|
+
# file.write(' # Betatron cleaning\n')
|
|
450
|
+
# sel_fam = [fam for fam in LHC_families if re.match('.*7', fam) and (fam in fams_in_dict)]
|
|
451
|
+
# printed_families += sel_fam
|
|
452
|
+
# _print_values(sel_fam, self._family_dict, file, spacing=' - &', mapping=True)
|
|
453
|
+
|
|
454
|
+
# # Injection protection
|
|
455
|
+
# file.write(' # Injection protection\n')
|
|
456
|
+
# sel_fam = [fam for fam in LHC_families if (fam in ['tcli', 'tdi']) and (fam in fams_in_dict)]
|
|
457
|
+
# printed_families += sel_fam
|
|
458
|
+
# _print_values(sel_fam, self._family_dict, file, spacing=' - &', mapping=True)
|
|
459
|
+
|
|
460
|
+
# # Dump protection
|
|
461
|
+
# file.write(' # Dump protection\n')
|
|
462
|
+
# sel_fam = [fam for fam in LHC_families if (fam in ['tcdq', 'tcsp', 'tcstcdq']) and (fam in fams_in_dict)]
|
|
463
|
+
# printed_families += sel_fam
|
|
464
|
+
# _print_values(sel_fam, self._family_dict, file, spacing=' - &', mapping=True)
|
|
465
|
+
|
|
466
|
+
# # Physics background / debris
|
|
467
|
+
# file.write(' # Physics background / debris\n')
|
|
468
|
+
# sel_fam = [fam for fam in LHC_families if ((re.match('tc[lt][0-9dp].*', fam)) or (fam in ['tcryo', 'tcxrp'])) and (fam in fams_in_dict)]
|
|
469
|
+
# printed_families += sel_fam
|
|
470
|
+
# _print_values(sel_fam, self._family_dict, file, spacing=' - &', mapping=True)
|
|
471
|
+
|
|
472
|
+
# # Other families
|
|
473
|
+
# if set(printed_families) != set(fams_in_dict):
|
|
474
|
+
# file.write(' # Other families\n')
|
|
475
|
+
# _print_values(set(fams_in_dict) - set(printed_families), self._family_dict, file, spacing=' - &', mapping=True)
|
|
476
|
+
# else:
|
|
477
|
+
# file.write(' # Families\n')
|
|
478
|
+
# _print_values(self._family_dict.keys(), self._family_dict, file, spacing=' - &', mapping=True)
|
|
479
|
+
|
|
480
|
+
# # Emittance section
|
|
481
|
+
# ex = self.nemitt_x
|
|
482
|
+
# ey = self.nemitt_y
|
|
483
|
+
# file.write(f'\nemittance:\n x: {ex}\n y: {ey}\n')
|
|
484
|
+
|
|
485
|
+
# # Collimators section
|
|
486
|
+
# file.write('\ncollimators:\n')
|
|
487
|
+
# b1_colls, b2_colls, bx_colls = [], [], []
|
|
488
|
+
# for coll in self.to_pandas().index:
|
|
489
|
+
# if coll == 'tclia.4r2' or coll == 'tclia.4l8': # TODO: hardcoded!!!
|
|
490
|
+
# b1_colls.append(coll)
|
|
491
|
+
# b2_colls.append(coll)
|
|
492
|
+
# elif coll[-2:] == 'b1':
|
|
493
|
+
# b1_colls.append(coll)
|
|
494
|
+
# elif coll[-2:] == 'b2':
|
|
495
|
+
# b2_colls.append(coll)
|
|
496
|
+
# else:
|
|
497
|
+
# bx_colls.append(coll)
|
|
498
|
+
|
|
499
|
+
# # Handle special cases for collimators
|
|
500
|
+
# if (('tclia.4r2' in b1_colls) or ('tclia.4l8' in b1_colls)) and (len(b1_colls) <= 2):
|
|
501
|
+
# b1_colls = []
|
|
502
|
+
# if (('tclia.4r2' in b2_colls) or ('tclia.4l8' in b2_colls)) and (len(b2_colls) <= 2):
|
|
503
|
+
# b2_colls = []
|
|
504
|
+
|
|
505
|
+
# # Print collimators for each beam
|
|
506
|
+
# if len(b1_colls) > 0:
|
|
507
|
+
# _print_colls(b1_colls, self, 'b1', file)
|
|
508
|
+
# if len(b2_colls) > 0:
|
|
509
|
+
# _print_colls(b2_colls, self, 'b2', file)
|
|
510
|
+
# if len(bx_colls) > 0:
|
|
511
|
+
# _print_colls(bx_colls, self, 'bx', file)
|
|
512
|
+
# 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.')
|
|
511
513
|
|
|
512
514
|
|
|
513
515
|
# ====================================
|
|
@@ -539,27 +541,14 @@ class CollimatorDatabase:
|
|
|
539
541
|
+ f"(or xtrack.Drift)!\nPlease check the name, or correct the "
|
|
540
542
|
+ f"element.")
|
|
541
543
|
|
|
542
|
-
def _create_collimator(self,
|
|
543
|
-
|
|
544
|
-
self._check_installed(line, name, collimator_class)
|
|
544
|
+
def _create_collimator(self, cls, line, name, **kwargs):
|
|
545
|
+
self._check_installed(line, name, cls)
|
|
545
546
|
if kwargs.pop('verbose', False):
|
|
546
|
-
print(f"Installing {name:20} as {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
el
|
|
551
|
-
self._elements[name] = el
|
|
552
|
-
|
|
553
|
-
def _create_crystal(self, line, crystal_class, name, **kwargs):
|
|
554
|
-
assert issubclass(crystal_class, BaseCrystal)
|
|
555
|
-
self._check_installed(line, name, crystal_class)
|
|
556
|
-
if kwargs.pop('verbose', False):
|
|
557
|
-
print(f"Installing {name:20} as {crystal_class.__name__}")
|
|
558
|
-
el = crystal_class(gap=self[name]['gap'], angle=self[name]['angle'],
|
|
559
|
-
length=self[name]['length'], side=self[name]['side'],
|
|
560
|
-
bending_radius=self[name]['bending_radius'],
|
|
561
|
-
width=self[name]['width'], height=self[name]['height'],
|
|
562
|
-
_tracking=False, **kwargs)
|
|
547
|
+
print(f"Installing {name:20} as {cls.__name__}")
|
|
548
|
+
prop_dict = {kk: vv for kk, vv in self[name].items() \
|
|
549
|
+
if kk in cls._xofields or kk in cls._store_in_to_dict}
|
|
550
|
+
prop_dict.update(kwargs)
|
|
551
|
+
el = cls(**prop_dict)
|
|
563
552
|
el.emittance = [self.nemitt_x, self.nemitt_y]
|
|
564
553
|
self._elements[name] = el
|
|
565
554
|
|
|
@@ -567,9 +556,9 @@ class CollimatorDatabase:
|
|
|
567
556
|
names = self._get_names_from_line(line, names, families)
|
|
568
557
|
for name in names:
|
|
569
558
|
if self[name]['bending_radius'] is None:
|
|
570
|
-
self._create_collimator(
|
|
559
|
+
self._create_collimator(BlackAbsorber, line, name, verbose=verbose)
|
|
571
560
|
else:
|
|
572
|
-
self.
|
|
561
|
+
self._create_collimator(BlackCrystal, line, name, verbose=verbose)
|
|
573
562
|
elements = [self._elements[name] for name in names]
|
|
574
563
|
line.collimators.install(names, elements, need_apertures=need_apertures)
|
|
575
564
|
|
|
@@ -578,12 +567,11 @@ class CollimatorDatabase:
|
|
|
578
567
|
for name in names:
|
|
579
568
|
mat = SixTrack_to_xcoll(self[name]['material'])
|
|
580
569
|
if self[name]['bending_radius'] is None:
|
|
581
|
-
self._create_collimator(
|
|
570
|
+
self._create_collimator(EverestCollimator, line, name, material=mat[0],
|
|
582
571
|
verbose=verbose)
|
|
583
572
|
else:
|
|
584
|
-
self.
|
|
585
|
-
|
|
586
|
-
miscut=self[name]['miscut'])
|
|
573
|
+
self._create_collimator(EverestCrystal, line, name, material=mat[1],
|
|
574
|
+
verbose=verbose)
|
|
587
575
|
elements = [self._elements[name] for name in names]
|
|
588
576
|
line.collimators.install(names, elements, need_apertures=need_apertures)
|
|
589
577
|
|
xcoll/general.py
CHANGED
xcoll/initial_distribution.py
CHANGED
|
@@ -57,8 +57,14 @@ def generate_pencil_on_collimator(line, name, num_particles, *, side='+-', penci
|
|
|
57
57
|
if twiss is None:
|
|
58
58
|
twiss = line.twiss()
|
|
59
59
|
|
|
60
|
-
# Is it converging or diverging?
|
|
61
|
-
|
|
60
|
+
# Is it converging or diverging?
|
|
61
|
+
# TODO: dispersion might change this
|
|
62
|
+
# TODO: this should be checked jaw by jaw (we are currently checking the left jaw - watch out for sign of tilt of right jaw)
|
|
63
|
+
# TODO: skew collimators
|
|
64
|
+
tilt = coll.tilt[0] if isinstance(coll.tilt, list) else coll.tilt
|
|
65
|
+
betatron_angle = coll.gap * coll.divergence
|
|
66
|
+
tolerance_tilt = 1e-12 # 0.1 urad tolerance on jaw tilt => we prioritise converging
|
|
67
|
+
is_converging = tilt + tolerance_tilt >= betatron_angle
|
|
62
68
|
print(f"Collimator {name} is {'con' if is_converging else 'di'}verging.")
|
|
63
69
|
|
|
64
70
|
beam_sizes = twiss.get_beam_covariance(nemitt_x=coll.nemitt_x, nemitt_y=coll.nemitt_y)
|
xcoll/line_tools.py
CHANGED
|
@@ -33,7 +33,7 @@ class XcollScatteringAPI:
|
|
|
33
33
|
if nemitt_y is None:
|
|
34
34
|
nemitt_y = el.nemitt_y
|
|
35
35
|
if not np.isclose(el.nemitt_x, nemitt_x) \
|
|
36
|
-
or not np.isclose(el.
|
|
36
|
+
or not np.isclose(el.nemitt_y, nemitt_y):
|
|
37
37
|
raise ValueError("Not all collimators have the same "
|
|
38
38
|
+ "emittance. This is not supported.")
|
|
39
39
|
if hasattr(el, 'enable_scattering'):
|
|
@@ -243,7 +243,7 @@ class XcollCollimatorAPI:
|
|
|
243
243
|
tw_upstream, tw_downstream = self.get_optics_at(names, twiss=twiss)
|
|
244
244
|
beta_gamma_rel = self.line.particle_ref._xobject.gamma0[0]*self.line.particle_ref._xobject.beta0[0]
|
|
245
245
|
for coll in names:
|
|
246
|
-
self.line[coll].assign_optics(name=coll, nemitt_x=nemitt_x, nemitt_y=
|
|
246
|
+
self.line[coll].assign_optics(name=coll, nemitt_x=nemitt_x, nemitt_y=nemitt_y, twiss_upstream=tw_upstream,
|
|
247
247
|
twiss_downstream=tw_downstream, beta_gamma_rel=beta_gamma_rel)
|
|
248
248
|
|
|
249
249
|
def open(self, names=None):
|
|
@@ -282,22 +282,22 @@ class XcollCollimatorAPI:
|
|
|
282
282
|
|
|
283
283
|
def assign_optics_to_collimators(line, nemitt_x=None, nemitt_y=None, twiss=None):
|
|
284
284
|
warn("The function xcoll.assign_optics_to_collimators() is deprecated and will be "
|
|
285
|
-
+ "removed in the future. Please use line.
|
|
285
|
+
+ "removed in the future. Please use line.collimators.assign_optics() instead.", FutureWarning)
|
|
286
286
|
line.collimators.assign_optics(nemitt_x=nemitt_x, nemitt_y=nemitt_y, twiss=twiss)
|
|
287
287
|
|
|
288
288
|
def get_optics_at(names, *, twiss=None, line=None):
|
|
289
289
|
warn("The function xcoll.get_optics_at() is deprecated and will be "
|
|
290
|
-
+ "removed in the future. Please use line.
|
|
290
|
+
+ "removed in the future. Please use line.collimators.get_optics_at() instead.", FutureWarning)
|
|
291
291
|
return line.collimators.get_optics_at(names=names, twiss=twiss)
|
|
292
292
|
|
|
293
293
|
def open_collimators(line, names=None):
|
|
294
294
|
warn("The function xcoll.open_collimators() is deprecated and will be "
|
|
295
|
-
+ "removed in the future. Please use line.
|
|
295
|
+
+ "removed in the future. Please use line.collimators.open_collimators() instead.", FutureWarning)
|
|
296
296
|
line.collimators.open(names=names)
|
|
297
297
|
|
|
298
298
|
def send_to_parking(line, names=None):
|
|
299
299
|
warn("The function xcoll.send_to_parking() is deprecated and will be "
|
|
300
|
-
+ "removed in the future. Please use line.
|
|
300
|
+
+ "removed in the future. Please use line.collimators.send_to_parking() instead.", FutureWarning)
|
|
301
301
|
line.collimators.to_parking(names=names)
|
|
302
302
|
|
|
303
303
|
def enable_scattering(line):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: xcoll
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.11
|
|
4
4
|
Summary: Xsuite collimation package
|
|
5
5
|
Home-page: https://github.com/xsuite/xcoll
|
|
6
6
|
License: Apache 2.0
|
|
@@ -18,10 +18,10 @@ Provides-Extra: tests
|
|
|
18
18
|
Requires-Dist: numpy (>=1.0)
|
|
19
19
|
Requires-Dist: pandas (>=1.4)
|
|
20
20
|
Requires-Dist: ruamel-yaml (>=0.17.31,<0.18.0) ; extra == "tests"
|
|
21
|
-
Requires-Dist: xdeps (>=0.
|
|
21
|
+
Requires-Dist: xdeps (>=0.8.1)
|
|
22
22
|
Requires-Dist: xobjects (>=0.4.5)
|
|
23
|
-
Requires-Dist: xpart (>=0.19.
|
|
24
|
-
Requires-Dist: xtrack (>=0.
|
|
23
|
+
Requires-Dist: xpart (>=0.19.3)
|
|
24
|
+
Requires-Dist: xtrack (>=0.70.3)
|
|
25
25
|
Project-URL: Repository, https://github.com/xsuite/xcoll
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
|