#!/usr/bin/env python
# --------------------------------------------------------
# This is a collection of aperture classes for linac lattices
# --------------------------------------------------------
import math
import sys
import os
# import the auxiliary classes
from orbit.utils import orbitFinalize
from orbit.py_linac.lattice import BaseLinacNode, Quad
# import BaseAperture and Phase and Eneregy Apertures C++ classes
from orbit.core.aperture import BaseAperture, PhaseAperture, EnergyAperture
# ---- here we use only primitive aperture shapes - circle, ellipse, and rectangular
from orbit.core.aperture import PrimitiveApertureShape
[docs]class LinacApertureNode(BaseLinacNode):
"""
The aperture classes removes particles from bunch and places them in the lostbunch
if their coordinates are not inside the aperture:
The shape variable could be:
1 is circle (a is a radius)
2 is elipse (a and b are a half-axises)
3 is rectangle (a and b are a half-horizontal and vertical sizes)
c and d parameters are x and y offsets of the center
"""
def __init__(self, shape, a, b, pos=0.0, c=0.0, d=0.0, name="aperture"):
BaseLinacNode.__init__(self, name)
self.shape = shape
self.a = a
self.b = b
self.c = c
self.d = d
self.aperture = BaseAperture()
# ---- aperture shape definition
apertureShape = None
if shape == 1:
radius = self.a
apertureShape = PrimitiveApertureShape("circle", radius)
if shape == 2:
x_half_size = self.a
y_half_size = self.b
apertureShape = PrimitiveApertureShape("ellipse", x_half_size, y_half_size)
if shape == 3:
x_half_size = self.a
y_half_size = self.b
apertureShape = PrimitiveApertureShape("rectangular", x_half_size, y_half_size)
if apertureShape == None:
orbitFinalize("LinacApertureNode constructor. shape parameter should be 1,2,3 only.Stop")
# ------------------------------
self.aperture.setApertureShape(apertureShape)
self.aperture.name(name)
self.setPosition(pos)
self.lost_particles_n = 0
[docs] def setName(self, name="no name"):
"""
Method. Sets the name.
"""
BaseLinacNode.setName(self, name)
self.aperture.name(name)
[docs] def track(self, paramsDict):
bunch = paramsDict["bunch"]
if "lostbunch" in paramsDict:
lostbunch = paramsDict["lostbunch"]
self.aperture.checkBunch(bunch, lostbunch)
else:
self.aperture.checkBunch(bunch)
self.lost_particles_n = self.aperture.getNumberOfLost()
[docs] def trackDesign(self, paramsDict):
"""
This method does nothing for the aperture case.
"""
pass
[docs] def setPosition(self, pos):
BaseLinacNode.setPosition(self, pos)
self.aperture.position(self.getPosition())
[docs] def getNumberOfLostParticles(self):
return self.lost_particles_n
[docs] def getBaseAperture(self):
"""
Retirns BaseAperture that allow accsess to aperture shape through getApertureShape,
or replacing the shape with setApertureShape(newApertureShape)
"""
return self.aperture
[docs]class CircleLinacApertureNode(LinacApertureNode):
"""
The curcular aperture shape = 1
"""
def __init__(self, radius, pos=0.0, c=0.0, d=0.0, name="aperture"):
LinacApertureNode.__init__(self, 1, radius, radius, pos, c, d, name)
[docs]class EllipseLinacApertureNode(LinacApertureNode):
"""
The ellipse aperture shape = 2
"""
def __init__(self, a, b, pos=0.0, c=0.0, d=0.0, name="aperture"):
LinacApertureNode.__init__(self, 2, a, b, pos, c, d, name)
[docs]class RectangleLinacApertureNode(LinacApertureNode):
"""
The rectangle aperture shape = 3
"""
def __init__(self, a, b, pos=0.0, c=0.0, d=0.0, name="aperture"):
LinacApertureNode.__init__(self, 3, a, b, pos, c, d, name)
[docs]class LinacPhaseApertureNode(BaseLinacNode):
"""
The phase aperture classes removes particles from bunch and places them in the lostbunch
if their phases are not inside the min-max phases.
"""
def __init__(self, frequency=402.5e6, name="phase_aperture"):
BaseLinacNode.__init__(self, name)
self.aperture = PhaseAperture(frequency)
self.lost_particles_n = 0
[docs] def setMinMaxPhase(self, minPhase, maxPhase):
self.aperture.setMinMaxPhase(minPhase, maxPhase)
[docs] def getMinMaxPhase(self):
return self.aperture.getMinMaxPhase()
[docs] def setRfFrequency(self, frequency):
self.aperture.setRfFrequency(frequency)
[docs] def getRfFrequency(self):
return self.aperture.getRfFrequency()
[docs] def setPosition(self, pos):
BaseLinacNode.setPosition(self, pos)
self.aperture.setPosition(self.getPosition())
[docs] def track(self, paramsDict):
bunch = paramsDict["bunch"]
n_parts = bunch.getSize()
if "lostbunch" in paramsDict:
lostbunch = paramsDict["lostbunch"]
self.aperture.checkBunch(bunch, lostbunch)
else:
self.aperture.checkBunch(bunch)
self.lost_particles_n = n_parts - bunch.getSize()
[docs] def trackDesign(self, paramsDict):
"""
This method does nothing for the aperture case.
"""
pass
[docs] def getNumberOfLostParticles(self):
return self.lost_particles_n
[docs]class LinacEnergyApertureNode(BaseLinacNode):
"""
The phase aperture classes removes particles from bunch and places them in the lostbunch
if their phases are not inside the min-max energy.
"""
def __init__(self, name="energy_aperture"):
BaseLinacNode.__init__(self, name)
self.aperture = EnergyAperture()
self.lost_particles_n = 0
self.eKin_design = 0.0
[docs] def setMinMaxEnergy(self, minEnergy, maxEnergy):
self.aperture.setMinMaxEnergy(minEnergy, maxEnergy)
[docs] def getMinMaxEnergy(self):
return self.aperture.getMinMaxEnergy()
[docs] def setPosition(self, pos):
BaseLinacNode.setPosition(self, pos)
self.aperture.setPosition(self.getPosition())
[docs] def track(self, paramsDict):
bunch = paramsDict["bunch"]
n_parts = bunch.getSize()
if "lostbunch" in paramsDict:
lostbunch = paramsDict["lostbunch"]
self.aperture.checkBunch(bunch, lostbunch)
else:
self.aperture.checkBunch(bunch)
self.lost_particles_n = n_parts - bunch.getSize()
[docs] def trackDesign(self, paramsDict):
"""
This method memorizes the kinetic energy of the synchronous particle.
"""
bunch = paramsDict["bunch"]
self.eKin_design = bunch.getSyncParticle().kinEnergy()
[docs] def getNumberOfLostParticles(self):
return self.lost_particles_n
[docs] def getDesignKinEnergy(self):
return self.eKin_design