1 '''Defines the BeamTree class for theia.'''
2
3
4
5
6
7
8
9
10
11
12
13
14 import numpy as np
15 from ..helpers import settings
16 from ..helpers.units import mm, deg
17 from ..helpers.tools import formatter
18 from ..helpers.geometry import rectToSph, linePlaneInter
19
21 '''
22
23 BeamTree class.
24
25 A BeamTree is a binary tree which allows to keep track of the beams as they
26 are traced throughout the optical setup. The Root of the tree is a Gaussian
27 beam and the other attributes are the daughter trees and all the data of the
28 interaction producing these with the Root beam
29
30 *=== Attributes ===*
31 Name: class attribute, name of object. [string]
32 Root: beam of this node of the tree. [GaussianBeam]
33 T: beam resulting from the transmission of the Root beam. [BeamTree]
34 R: beam resulting from the reflection of the Root beam. [BeamTree]
35
36 '''
37 Name = "BeamTree"
38
39 - def __init__(self, Root = None,
40 T = None, R = None):
41 '''BeamTree initializer.'''
42 self.Root = Root
43 self.T = T
44 self.R = R
45
47 '''String representation of a BeamTree, for print(tree).'''
48 return formatter(self.lines())
49
51 '''Returns the list of lines necessary to print the object.'''
52 ans = []
53 ans.append("Tree: {")
54 ans.append("Root beam: %s" %str(self.Root.Ref))
55 ans.append("Number of beams: %s" %str(self.numberOfBeams()))
56 ans.append("}")
57
58 return ans
59
61 '''Returns the string representation the tree of beams.
62
63 '''
64 before = ["Tree: Root beam = %s {" %str(self.Root.Ref)]
65 after = ["}"]
66 return formatter(before + self.beamLines() + after)
67
69 '''Returns the list of lines necessary to print the list of beams.
70
71 '''
72 ans = []
73 if self.Root is not None:
74 ans = self.Root.lines()
75 if self.R is not None:
76 ans = ans + self.R.beamLines()
77 if self.T is not None:
78 ans = ans + self.T.beamLines()
79
80 return ans
81
83 '''Return the total number of beams.'''
84 if self.Root is None:
85 return 0
86
87 if self.T is None and self.R is None:
88 return 1
89 elif self.T is None and self.R is not None:
90 return 1 + self.R.numberOfBeams()
91 elif self.T is not None and self.R is None:
92 return 1 + self.T.numberOfBeams()
93 else:
94 return 1 + self.T.numberOfBeams() + self.R.numberOfBeams()
95
97 '''Return the list of lines to write the output of simulation.'''
98 sList = []
99 if self.Root is not None:
100 if self.Root.Optic is not None:
101 if self.Root.Length > 0.:
102 if self.R is not None and self.R.Root is not None:
103 sList = ['(%s, %s) %sm (%s, %s) %s {' \
104 %(self.Root.Optic, self.Root.Face,
105 str(self.Root.Length), self.R.Root.Optic,
106 self.R.Root.Face, self.Root.Ref)]
107 elif self.T is not None and self.T.Root is not None:
108 sList = ['(%s, %s) %sm (%s, %s) %s {' \
109 %(self.Root.Optic, self.Root.Face,
110 str(self.Root.Length), self.T.Root.Optic,
111 self.T.Root.Face, self.Root.Ref)]
112 else:
113 sList = ['(%s, %s) [end] %s {' \
114 %(self.Root.Optic, self.Root.Face, self.Root.Ref)]
115 else:
116 sList = ['(%s, %s) [open] %s {' \
117 %(self.Root.Optic, self.Root.Face, self.Root.Ref)]
118 else:
119 if self.Root.Length > 0.:
120 if self.R is not None and self.R.Root is not None:
121 sList = ['[InBeam] %sm (%s, %s) %s {' \
122 %(str(self.Root.Length), self.R.Root.Optic,
123 self.R.Root.Face, self.Root.Ref)]
124 elif self.T is not None and self.T.Root is not None:
125 sList = ['[InBeam] %sm (%s, %s) %s {' \
126 %(str(self.Root.Length), self.T.Root.Optic,
127 self.T.Root.Face, self.Root.Ref)]
128 else:
129 sList = ['[InBeam] %sm [end] %s {' \
130 %(str(self.Root.Length), self.Root.Ref)]
131 else:
132 sList = ['[InBeam] [Open] %s {' %self.Root.Ref]
133 sList.append("Waist Pos: %sm" %str(self.Root.waistPos()))
134 sList.append("Waist Size: (%s, %s)mm" \
135 %(str(self.Root.waistSize()[0]/mm),
136 str(self.Root.waistSize()[1]/mm)))
137 sph = rectToSph(self.Root.Dir)
138 sList.append("Direction: (%s, %s)deg" %(str(sph[0]/deg),
139 str(sph[1]/deg)))
140 sList.append('}')
141 if self.R is not None:
142 sList = sList + self.R.outputLines()
143 if self.T is not None:
144 sList = sList + self.T.outputLines()
145
146 return sList
147
148
149 -def treeOfBeam(srcBeam, optList, order, threshold):
150 '''Function to calculate the tree of daughter beams of srcBeam.
151
152 srcBeam: Input beam. [GaussianBeam]
153 optList: List of optical components of the setup. [list of OpticalComponent]
154 order: order of simulation. [integer]
155 threshold: power threshold for daughter beams. [float]
156
157 Returns a BeamTree.
158
159 '''
160 if len(optList) == 0:
161
162 return BeamTree(Root = srcBeam)
163
164 if srcBeam is None:
165
166 return BeamTree()
167
168
169 clippingOpts = ["Mirror", "ThinLens", "ThickLens"]
170 width = srcBeam.width(srcBeam.Length)
171 waist = max(width[0],
172 width[1])
173
174
175 dist = settings.inf
176 finalOpt = None
177
178
179 for opt in optList:
180 dicoisHit = opt.isHit(srcBeam)
181 if dicoisHit['isHit'] and dicoisHit['distance'] < dist:
182 dist = dicoisHit['distance']
183 finalOpt = opt
184
185
186 if settings.antiClip:
187 for opt in optList:
188 if opt.Name in clippingOpts:
189
190 HClipDic = linePlaneInter(srcBeam.Pos, srcBeam.Dir,
191 opt.HRCenter, opt.HRNorm,
192 opt.Dia + 2 * settings.clipFactor * waist)
193
194 AClipDic = linePlaneInter(srcBeam.Pos, srcBeam.Dir,
195 opt.ARCenter, opt.ARNorm,
196 opt.Dia + 2 * settings.clipFactor * waist)
197 if HClipDic['isHit'] and HClipDic['distance'] < dist \
198 or AClipDic['isHit'] and AClipDic['distance'] < dist:
199 print "theia: Warning: Anti-Clipping of beam %s on %s."\
200 %(srcBeam.Ref, opt.Ref)
201
202
203 if finalOpt is None:
204
205 if settings.info:
206 print "theia: Info: Reached open beam %s." %srcBeam.Ref
207 return BeamTree(Root = srcBeam)
208
209
210 finalisHit = finalOpt.isHit(srcBeam)
211 finalHit = finalOpt.hit(srcBeam, order = order, threshold = threshold)
212
213
214 isClipped = False
215 if not finalisHit['face'] == 'Side' and finalOpt.Name in clippingOpts:
216 center = finalOpt.HRCenter if finalisHit['face'] == 'HR'\
217 else finalOpt.ARCenter
218 distance = np.linalg.norm(finalisHit['intersection point'] - center)
219 isClipped = distance + settings.clipFactor * waist > finalOpt.Dia/2.
220
221
222 if isClipped and settings.warning:
223 print "theia: Warning: Clipping of beam %s on (%s, %s)."\
224 %(srcBeam.Ref, finalOpt.Ref, finalisHit['face'])
225
226 return BeamTree(Root = srcBeam,
227 T = treeOfBeam(finalHit['t'], optList, order, threshold),
228 R = treeOfBeam(finalHit['r'], optList, order, threshold))
229