Package theia :: Package optics :: Module beam
[hide private]
[frames] | no frames]

Source Code for Module theia.optics.beam

  1  '''Defines the GaussianBeam class for theia.''' 
  2   
  3  # Provides: 
  4  #   class GaussianBeam 
  5  #       __init__ 
  6  #       userBeam 
  7  #       __str__ 
  8  #       lines 
  9  #       Q 
 10  #       QParam 
 11  #       ROC 
 12  #       waistPos 
 13  #       rayleigh 
 14  #       width 
 15  #       waistSize 
 16  #       gouy 
 17   
 18  import numpy as np 
 19  from ..helpers import geometry 
 20  from ..helpers.tools import formatter 
 21  from ..helpers.units import pi, nm, deg, mm 
 22   
23 -class GaussianBeam(object):
24 ''' 25 26 GaussianBeam class. 27 28 This class represents general astigmatic Gaussian beams in 3D space. 29 These are the objects that are intended to interact with the optical 30 components during the ray tracing and that are rendered in 3D thanks to 31 FreeCAD. 32 33 *=== Attributes ===* 34 BeamCount: class attribute, counts beams. [integer] 35 QTens: general astigmatic complex curvature tensor at the origin. 36 [np. array of complex] 37 N: Refraction index of the medium in which the beam is placed. [float] 38 Wl: Wave-length in vacuum of the beam (frequency never changes). [float] 39 P: Power of the beam. [float] 40 Pos: Position in 3D space of the origin of the beam. [3D vector] 41 Dir: Normalized direction in 3D space of the beam axis. [3D vector] 42 U: A tuple of unitary vectors which along with Dir form a direct orthonormal 43 basis in which the Q tensor is expressed. [tuple of 3D vectors] 44 Name: Name of the beam if any. [string] 45 Ref: Reference to the beam. [string] 46 OptDist: Optical length. [float] 47 Length: Geometrical length of the beam. [float] 48 StrayOrder: Number representing the *strayness* of the beam. If the beams 49 results from a transmission on a HR surface or a reflection on a AR 50 surface, then its StrayOrder is the StrayOrder of the parent beam + 1. 51 [integer] 52 Optic: Ref of optic where the beam departs from (None if laser). [string] 53 Face: face of the optic where the beam departs from. [string] 54 55 ''' 56 BeamCount = 0 # counts beams 57
58 - def __init__(self, Q, N, Wl, P, Pos, Dir, Ux, Uy, Name, Ref, OptDist, 59 Length, StrayOrder, Optic, Face):
60 '''Beam initializer. 61 62 This is the initializer used internally for beam creation, for user 63 inputed beams, see class method userGaussianBeam. 64 65 Returns a Gaussian beam with attributes as the parameters. 66 67 ''' 68 69 # external params 70 self.N = N 71 self.Wl = Wl 72 self.P = P 73 self.OptDist = OptDist 74 self.Length = Length 75 self.StrayOrder = StrayOrder 76 77 self.Name = Name 78 self.Ref = Ref 79 80 self.Pos = Pos 81 self.Dir = Dir 82 83 # orthonormal basis in which Q is expressed 84 self.U = (Ux, Uy) 85 86 # Curvature tensor 87 self.QTens = np.array(Q, dtype = np.complex64) 88 89 #origin optics 90 self.Optic = Optic 91 self.Face = Face 92 93 self.__class__.BeamCount = self.__class__.BeamCount + 1
94
95 - def __str__(self):
96 '''String representation of the beam, when calling print(beam). 97 98 ''' 99 return formatter(self.lines())
100
101 - def lines(self):
102 '''Returns the list of lines necessary to print the object. 103 104 ''' 105 ans = [] 106 ans.append("Beam: " + self.Name + " (" + self.Ref + ") " + "{") 107 ans.append("Power: " + str(self.P) + "W/"\ 108 +"Index: " + str(self.N)\ 109 +"/Wavelength: "+str(self.Wl/nm)+"nm/Length: " + str(self.Length) + "m") 110 ans.append("Order: " + str(self.StrayOrder)) 111 ans.append("Origin: " + str(self.Pos)) 112 113 sph = geometry.rectToSph(self.Dir) 114 ans.append("Direction: (" + str(sph[0]/deg) + ', ' \ 115 + str(sph[1]/deg) + ')deg') 116 117 sphx = geometry.rectToSph(self.U[0]) 118 ans.append("Ux: (" + str(sphx[0]/deg) + ', ' \ 119 + str(sphx[1]/deg) + ')deg') 120 121 sphy = geometry.rectToSph(self.U[1]) 122 ans.append("Uy: (" + str(sphy[0]/deg) + ', ' \ 123 + str(sphy[1]/deg) + ')deg') 124 ans.append("Waist Pos: " + str(self.waistPos()) + 'm') 125 ans.append("Waist Size: (" \ 126 + str(self.waistSize()[0]/mm) + ', ' + str(self.waistSize()[1]/mm)\ 127 + ')mm') 128 ans.append("Rayleigh: " + str(self.rayleigh()) + "m") 129 ans.append("ROC: " + str(self.ROC())) 130 ans.append("}") 131 132 return ans
133
134 - def Q(self, d = 0.):
135 '''Return the Q tensor at a distance d of origin. 136 137 ''' 138 d = float(d) 139 I = np.array([[1., 0.], [0., 1.]], dtype=np.float64) 140 return np.matmul(np.linalg.inv(I + d * self.QTens),self.QTens)
141
142 - def QParam(self, d = 0.):
143 '''Compute the complex parameters q1 and q2 and theta of beam. 144 145 Returns a dictionary with keys: 146 '1': q1 [complex] 147 '2': q2 [complex] 148 'theta': theta [float] 149 ''' 150 d = float(d) 151 152 a = self.Q(d)[0][0] 153 b = self.Q(d)[0][1] 154 d = self.Q(d)[1][1] 155 156 q1inv = .5*(a + d + np.sqrt((a - d)**2. + 4.*b**2.)) 157 q2inv = .5*(a + d - np.sqrt((a - d)**2. + 4.*b**2.)) 158 159 if q1inv == q2inv: 160 theta = 0. 161 else: 162 theta = .5*np.arcsin(2.*b/(q1inv - q2inv)) 163 164 try: 165 a = 1/q1inv 166 except ZeroDivisionError: 167 a = np.inf 168 try: 169 b = 1/q2inv 170 except ZeroDivisionError: 171 b = np.inf 172 return {'1': a, '2': b, 'theta':theta}
173
174 - def ROC(self, dist = 0.):
175 '''Return the tuple of ROC of the beam. 176 177 ''' 178 dist = float(dist) 179 Q = self.QParam(dist) 180 try: 181 a = 1./np.real(1./Q['1']) 182 except FloatingPointError: 183 a = np.inf 184 try: 185 b = 1./np.real(1./Q['2']) 186 except FloatingPointError: 187 b = np.inf 188 189 return (a, b)
190
191 - def waistPos(self):
192 '''Return the tuple of positions of the waists of the beam along Dir. 193 194 ''' 195 Q = self.QParam(0.) 196 return (-np.real(Q['1']), -np.real(Q['2']))
197
198 - def rayleigh(self):
199 '''Return the tuple of Rayleigh ranges of the beam. 200 201 ''' 202 Q = self.QParam() 203 return (np.abs(np.imag(Q['1'])), np.abs(np.imag(Q['2'])))
204
205 - def width(self, d = 0.):
206 '''Return the tuple of beam widths. 207 208 ''' 209 d = float(d) 210 lam = self.Wl/self.N 211 zR = self.rayleigh() 212 D = self.waistPos() 213 214 return (np.sqrt((lam/pi)*((d - D[0])**2. + zR[0]**2.)/zR[0]) , 215 np.sqrt((lam/pi)*((d - D[1])**2. + zR[1]**2.)/zR[1]))
216
217 - def waistSize(self):
218 '''Return a tuple with the waist sizes in x and y. 219 220 ''' 221 pos = self.waistPos() 222 return (self.width(pos[0])[0], self.width(pos[1])[1] )
223
224 - def gouy(self, d = 0.):
225 '''Return the tuple of Gouy phases. 226 227 ''' 228 d = float(d) 229 zR = self.rayleigh() 230 WDist = self.waistPos() 231 return (np.arctan((d-WDist[0])/zR[0]), 232 np.arctan((d-WDist[1])/zR[1]))
233
234 -def userGaussianBeam(Wx = 1.e-3, Wy = 1.e-3, WDistx = 0., WDisty = 0., 235 Wl = 1064.e-9, P = 1., X = 0., Y = 0., Z = 0., 236 Theta = pi/2., Phi = 0., Alpha = 0., Name = None, 237 Ref = None):
238 '''Constructor used for user inputed beams, separated from the class 239 initializer because the internal state of a beam is very different from 240 the input of this user-defined beam. 241 242 Input parameters are processed to make arguments for the class 243 contructor and then the corresponding beam is returned. 244 ''' 245 246 #externs 247 P = float(P) 248 Pos = np.array([X, Y, Z], dtype = np.float64) 249 Dir = np.array([np.sin(Theta) * np.cos(Phi), 250 np.sin(Theta) * np.sin(Phi), 251 np.cos(Theta)], dtype = np.float64) 252 253 # basis for Q tensor 254 Alpha = float(Alpha) 255 (u1,v1) = geometry.basis(Dir) 256 v = np.cos(Alpha)*v1 - np.sin(Alpha)*u1 257 u = np.cos(Alpha)*u1 + np.sin(Alpha)*v1 258 259 # Q tensor for orthogonal beam 260 Wl = float(Wl) 261 Wx = float(Wx) 262 Wy = float(Wy) 263 qx = complex(- float(WDistx) + 1.j * pi*Wx**2./Wl ) 264 qy = complex(- float(WDisty) + 1.j * pi*Wy**2./Wl ) 265 QTens = np.array([[1./qx, 0.],[0., 1./qy]], 266 dtype = np.complex64) 267 268 if Name is None: 269 Name = "Beam" 270 else: 271 Name = Name 272 273 if Ref is None: 274 Ref = "Beam" + str(GaussianBeam.BeamCount) 275 else: 276 Ref = Ref 277 278 return GaussianBeam(Q = QTens, N = 1., Wl = Wl, P = P, 279 Pos = Pos, Dir = Dir, 280 Ux = u, Uy = v, Name = Name, Ref = Ref, OptDist = 0., 281 Length = 0., StrayOrder = 0, Optic = 'Laser', Face = 'Out')
282