File indexing completed on 2026-04-09 07:48:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 """
0022 sphere.py : SphereReflect intersection, polarization calculation and spatial plot
0023 =====================================================================================
0024
0025
0026 """
0027 import os, sys, logging, numpy as np
0028 log = logging.getLogger(__name__)
0029
0030 from mpl_toolkits.mplot3d import Axes3D
0031 import matplotlib.pyplot as plt
0032
0033 from opticks.ana.base import opticks_main
0034 from opticks.ana.nbase import vnorm
0035 from opticks.ana.evt import Evt, costheta_, cross_, norm_
0036 from opticks.ana.boundary import Boundary
0037
0038 deg = np.pi/180.
0039
0040
0041 class SphereReflect(object):
0042 def __init__(self, sel):
0043
0044 p0 = sel.rpost_(0)[:,:3]
0045 p1 = sel.rpost_(1)[:,:3]
0046 p_in = p1 - p0
0047
0048 pp = sel.rpost_(1)[:,:3]
0049 pl = sel.rpost_(2)[:,:3]
0050 p_out = pl - pp
0051
0052 e0 = sel.rpol_(0)
0053 e1 = sel.rpol_(1)
0054
0055 self.p0 = p0
0056 self.p1 = p1
0057 self.pl = pl
0058 self.p_in = p_in
0059 self.p_out = p_out
0060
0061 self.e0 = e0
0062 self.e1 = e1
0063
0064
0065 def check_radius(self):
0066 """
0067 Asymmetric wider distribution than expected, from ~99 to 101.4 until
0068 fixed sphere positioning, when get expected symmetry
0069
0070 ::
0071
0072 In [50]: r.min()
0073 Out[50]: 99.96880356309731
0074
0075 In [51]: r.max()
0076 Out[51]: 100.03083354506256
0077
0078 In [53]: np.average(r)
0079 Out[53]: 100.00002525999686
0080
0081
0082 """
0083
0084 r = vnorm(self.p1)
0085 log.info("r min/max %s %s " % (r.min(), r,max() ))
0086
0087 plt.hist(r, bins=100)
0088
0089 return r
0090
0091 def intersection(self):
0092 """
0093 """
0094 origin = np.array([0,0,0])
0095 radius = 100.
0096
0097 direction = np.array([1,0,0])
0098
0099 ray_origin = self.p0
0100 ray_direction = np.tile(direction, len(ray_origin)).reshape(-1,3)
0101 center = np.tile(origin, len(ray_origin)).reshape(-1,3)
0102
0103 O = ray_origin - center
0104 D = ray_direction
0105
0106 b = np.sum( O*D, axis=1 )
0107 c = np.sum( O*O, axis=1 ) - radius*radius
0108
0109 disc = b*b-c
0110
0111
0112
0113 msk = disc > 0
0114
0115 sdisc = np.sqrt(disc)
0116 root1 = -b -sdisc
0117
0118 p1c = root1[:,None]*ray_direction + ray_origin
0119
0120 nrm = (O + D*root1[:,None])/radius
0121
0122 return p1c, nrm, msk
0123
0124
0125 def check_surface_normal(self):
0126 """
0127
0128 In [187]: nnrm = np.linalg.norm(nrm, 2, 1)
0129
0130 In [188]: nnrm[sr.msk].min()
0131 Out[188]: 0.99999999999999667
0132
0133 In [189]: nnrm[sr.msk].max()
0134 Out[189]: 1.0000000000000033
0135
0136 """
0137 sr = self
0138 p1c, nrm, msk = sr.intersection()
0139
0140 nnrm = vnorm(nrm)
0141
0142
0143 def check_intersection(self):
0144 """
0145
0146 In [155]: sr.mdp1[:,0].min()
0147 Out[155]: -1.7650434697386426
0148
0149 In [156]: sr.mdp1[:,0].max()
0150 Out[156]: 1.8097476126588909
0151
0152 plt.hist(sr.dp1[sr.msk], bins=100) # sharp zero spike
0153
0154 """
0155 sr = self
0156
0157 p1c, nrm, msk = sr.intersection()
0158 p1 = self.p1
0159
0160 rperp = np.sqrt(np.sum( p1[:,1:3]*p1[:,1:3] , axis=1))
0161 dp1 = p1c - p1
0162 mdp1 = dp1[msk]
0163
0164 self.p1c = p1c
0165 self.msk = msk
0166 self.dp1 = dp1
0167 self.mdp1 = mdp1
0168 self.rperp = rperp
0169
0170 nrm = norm_(p1c)
0171
0172
0173 idir = norm_(self.p_in)
0174 ndir = norm_(self.p_out)
0175 trans = np.cross(idir, nrm )
0176 paral = norm_(np.cross( ndir, trans ))
0177
0178 self.nrm = nrm
0179 self.idir = idir
0180 self.ndir = ndir
0181 self.trans = trans
0182 self.paral = paral
0183
0184
0185
0186
0187
0188
0189
0190 def check_polarization(self):
0191 """
0192 Direction of incident rays and reflection/transmission rays together
0193 with surface normal allow the orthonormal bases at each stage to be calculated.
0194 With which the polarisation can be projected upon to see if it makes sense.
0195
0196 Polarized in direction of photon(not real) will that mess things up?::
0197
0198 In [78]: e0 = sel.recpolarization(0)
0199
0200 In [79]: e1 = sel.recpolarization(1)
0201
0202 In [80]: e0
0203 Out[80]:
0204 array([[ 1., 0., 0.],
0205 [ 1., 0., 0.],
0206 [ 1., 0., 0.],
0207 ...,
0208 [ 1., 0., 0.],
0209 [ 1., 0., 0.],
0210 [ 1., 0., 0.]])
0211
0212 In [81]: e1
0213 Out[81]:
0214 array([[ 0.843, -0.528, -0.11 ],
0215 [-0.386, -0.835, -0.386],
0216 [-0.52 , 0.819, -0.252],
0217 ...,
0218 [-0.071, -0.15 , -0.984],
0219 [-0.236, -0.898, -0.378],
0220 [-0.362, -0.598, -0.717]])
0221
0222 In [82]: paral
0223 Out[82]:
0224 array([[ 0.841, -0.531, -0.108],
0225 [ 0.385, 0.838, 0.387],
0226 [ 0.517, -0.817, 0.255],
0227 ...,
0228 [ 0.072, 0.148, 0.986],
0229 [ 0.238, 0.896, 0.374],
0230 [ 0.363, 0.598, 0.715]])
0231
0232 In [83]: np.sum( e1*paral , axis=1)
0233 Out[83]: array([ 1. , -0.997, -1.002, ..., -0.998, -1.002, -1.001])
0234
0235 In [84]: trans
0236 Out[84]:
0237 array([[ 0. , 0.095, -0.469],
0238 [ 0. , 0.411, -0.89 ],
0239 [-0. , 0.287, 0.92 ],
0240 ...,
0241 [ 0. , 0.988, -0.148],
0242 [ 0. , 0.383, -0.916],
0243 [ 0. , 0.754, -0.631]])
0244
0245 In [85]: np.sum(e1*trans, axis=1)
0246 Out[85]: array([ 0.002, 0.001, 0.003, ..., -0.002, 0.003, 0.001])
0247
0248 """
0249 pass
0250
0251 def check_incident_sphere_pol(self):
0252 """
0253 ::
0254
0255 In [14]: xyz = evt_g4.p.rpost_(0)[:,:3]
0256
0257 In [16]: xyz[:,2] = 0
0258
0259 In [17]: xyz
0260 Out[17]:
0261 A([[-42.7747, -26.7342, 0. ],
0262 [ 88.5891, -44.203 , 0. ],
0263 [-63.3198, -62.6606, 0. ],
0264 ...,
0265 [-77.2729, 22.1198, 0. ],
0266 [ 57.7898, 29.7739, 0. ],
0267 [-86.3918, 1.8311, 0. ]])
0268
0269 In [18]: norm_(xyz)
0270 Out[18]:
0271 A([[-0.848 , -0.53 , 0. ],
0272 [ 0.8948, -0.4465, 0. ],
0273 [-0.7108, -0.7034, 0. ],
0274 ...,
0275 [-0.9614, 0.2752, 0. ],
0276 [ 0.889 , 0.458 , 0. ],
0277 [-0.9998, 0.0212, 0. ]])
0278
0279 In [19]: evt_g4.p.rpol_(0)
0280 Out[19]:
0281 array([[-0.8504, -0.5276, 0. ],
0282 [ 0.8976, -0.4488, 0. ],
0283 [-0.7087, -0.7008, 0. ],
0284 ...,
0285 [-0.9606, 0.2756, 0. ],
0286 [ 0.8898, 0.4567, 0. ],
0287 [-1. , 0.0236, 0. ]])
0288
0289 In [20]: evt_g4.s.rpol_(0)
0290 Out[20]:
0291 array([[ 0.5276, -0.8504, 0. ],
0292 [ 0.4488, 0.8976, 0. ],
0293 [ 0.7008, -0.7087, 0. ],
0294 ...,
0295 [-0.2756, -0.9606, 0. ],
0296 [-0.4567, 0.8898, 0. ],
0297 [-0.0236, -1. , 0. ]])
0298
0299 """
0300 pass
0301
0302
0303
0304
0305
0306 def spatial(self):
0307 """
0308 Initial observation of asymmetry,
0309
0310 *FIXED: THE SPHERE WAS OFFSET (-1,1): A HANGOVER TO AVOID LEAKY TRIANGLE CRACKS*
0311 after placing sphere at origin no asymmetry apparent
0312
0313 ::
0314
0315 In [44]: r.min()
0316 Out[44]: 99.96880356309731
0317
0318 In [45]: r.max()
0319 Out[45]: 100.03083354506256
0320
0321
0322 """
0323 fig = plt.figure()
0324
0325 x0 = self.p0[:,0]
0326 y0 = self.p0[:,1]
0327 z0 = self.p0[:,2]
0328
0329 x1 = self.p1[:,0]
0330 y1 = self.p1[:,1]
0331 z1 = self.p1[:,2]
0332
0333
0334 nr = 2
0335 nc = 3
0336 nb = 100
0337
0338 ax = fig.add_subplot(nr,nc,1)
0339 plt.hist2d(x0, y0, bins=nb)
0340 ax.set_xlabel("x0 y0")
0341
0342 ax = fig.add_subplot(nr,nc,2)
0343 plt.hist2d(x0, z0, bins=nb)
0344 ax.set_xlabel("x0 z0")
0345
0346 ax = fig.add_subplot(nr,nc,3)
0347 plt.hist2d(y0, z0, bins=nb)
0348 ax.set_xlabel("y0 z0")
0349
0350
0351 ax = fig.add_subplot(nr,nc,4)
0352 plt.hist2d(x1, y1, bins=nb)
0353 ax.set_xlabel("x1 y1")
0354
0355 ax = fig.add_subplot(nr,nc,5)
0356 plt.hist2d(x1, z1, bins=nb)
0357 ax.set_xlabel("x1 z1")
0358
0359 ax = fig.add_subplot(nr,nc,6)
0360 plt.hist2d(y1, z1, bins=nb)
0361 ax.set_xlabel("y1 z1")
0362
0363
0364
0365
0366 if __name__ == '__main__':
0367
0368 args = opticks_main(tag="-5", det="rainbow", src="torch")
0369
0370
0371 plt.ion()
0372 plt.close()
0373
0374 boundary = Boundary("Vacuum///MainH2OHale")
0375
0376
0377 seqs = ["TO BR SA"]
0378
0379
0380
0381 tag = args.tag
0382 if tag == "-6":
0383 label = "P G4"
0384 elif tag == "-5":
0385 label = "S G4"
0386 elif tag == "5":
0387 label = "S Op"
0388 elif tag == "6":
0389 label = "P Op"
0390 else:
0391 label = "label?"
0392
0393
0394 try:
0395 evt = Evt(tag=tag, det=args.det, src=args.src, seqs=seqs, label=label, args=args )
0396 except IOError as err:
0397 log.fatal(err)
0398 sys.exit(args.mrc)
0399
0400 log.info("loaded %s " % repr(evt))
0401
0402 sr = SphereReflect(evt)
0403
0404 p1 = sr.p1
0405
0406 sr.spatial()
0407
0408
0409
0410
0411
0412