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