polarization.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. The module implements routines to model the polarization of optical fields
  5. and can be used to calculate the effects of polarization optical elements on
  6. the fields.
  7. - Jones vectors.
  8. - Stokes vectors.
  9. - Jones matrices.
  10. - Mueller matrices.
  11. Examples
  12. ========
  13. We calculate a generic Jones vector:
  14. >>> from sympy import symbols, pprint, zeros, simplify
  15. >>> from sympy.physics.optics.polarization import (jones_vector, stokes_vector,
  16. ... half_wave_retarder, polarizing_beam_splitter, jones_2_stokes)
  17. >>> psi, chi, p, I0 = symbols("psi, chi, p, I0", real=True)
  18. >>> x0 = jones_vector(psi, chi)
  19. >>> pprint(x0, use_unicode=True)
  20. ⎡-ⅈ⋅sin(χ)⋅sin(ψ) + cos(χ)⋅cos(ψ)⎤
  21. ⎢ ⎥
  22. ⎣ⅈ⋅sin(χ)⋅cos(ψ) + sin(ψ)⋅cos(χ) ⎦
  23. And the more general Stokes vector:
  24. >>> s0 = stokes_vector(psi, chi, p, I0)
  25. >>> pprint(s0, use_unicode=True)
  26. ⎡ I₀ ⎤
  27. ⎢ ⎥
  28. ⎢I₀⋅p⋅cos(2⋅χ)⋅cos(2⋅ψ)⎥
  29. ⎢ ⎥
  30. ⎢I₀⋅p⋅sin(2⋅ψ)⋅cos(2⋅χ)⎥
  31. ⎢ ⎥
  32. ⎣ I₀⋅p⋅sin(2⋅χ) ⎦
  33. We calculate how the Jones vector is modified by a half-wave plate:
  34. >>> alpha = symbols("alpha", real=True)
  35. >>> HWP = half_wave_retarder(alpha)
  36. >>> x1 = simplify(HWP*x0)
  37. We calculate the very common operation of passing a beam through a half-wave
  38. plate and then through a polarizing beam-splitter. We do this by putting this
  39. Jones vector as the first entry of a two-Jones-vector state that is transformed
  40. by a 4x4 Jones matrix modelling the polarizing beam-splitter to get the
  41. transmitted and reflected Jones vectors:
  42. >>> PBS = polarizing_beam_splitter()
  43. >>> X1 = zeros(4, 1)
  44. >>> X1[:2, :] = x1
  45. >>> X2 = PBS*X1
  46. >>> transmitted_port = X2[:2, :]
  47. >>> reflected_port = X2[2:, :]
  48. This allows us to calculate how the power in both ports depends on the initial
  49. polarization:
  50. >>> transmitted_power = jones_2_stokes(transmitted_port)[0]
  51. >>> reflected_power = jones_2_stokes(reflected_port)[0]
  52. >>> print(transmitted_power)
  53. cos(-2*alpha + chi + psi)**2/2 + cos(2*alpha + chi - psi)**2/2
  54. >>> print(reflected_power)
  55. sin(-2*alpha + chi + psi)**2/2 + sin(2*alpha + chi - psi)**2/2
  56. Please see the description of the individual functions for further
  57. details and examples.
  58. References
  59. ==========
  60. .. [1] https://en.wikipedia.org/wiki/Jones_calculus
  61. .. [2] https://en.wikipedia.org/wiki/Mueller_calculus
  62. .. [3] https://en.wikipedia.org/wiki/Stokes_parameters
  63. """
  64. from sympy.core.numbers import (I, pi)
  65. from sympy.functions.elementary.complexes import (Abs, im, re)
  66. from sympy.functions.elementary.exponential import exp
  67. from sympy.functions.elementary.miscellaneous import sqrt
  68. from sympy.functions.elementary.trigonometric import (cos, sin)
  69. from sympy.matrices.dense import Matrix
  70. from sympy.simplify.simplify import simplify
  71. from sympy.physics.quantum import TensorProduct
  72. def jones_vector(psi, chi):
  73. """A Jones vector corresponding to a polarization ellipse with `psi` tilt,
  74. and `chi` circularity.
  75. Parameters
  76. ==========
  77. ``psi`` : numeric type or SymPy Symbol
  78. The tilt of the polarization relative to the `x` axis.
  79. ``chi`` : numeric type or SymPy Symbol
  80. The angle adjacent to the mayor axis of the polarization ellipse.
  81. Returns
  82. =======
  83. Matrix :
  84. A Jones vector.
  85. Examples
  86. ========
  87. The axes on the Poincaré sphere.
  88. >>> from sympy import pprint, symbols, pi
  89. >>> from sympy.physics.optics.polarization import jones_vector
  90. >>> psi, chi = symbols("psi, chi", real=True)
  91. A general Jones vector.
  92. >>> pprint(jones_vector(psi, chi), use_unicode=True)
  93. ⎡-ⅈ⋅sin(χ)⋅sin(ψ) + cos(χ)⋅cos(ψ)⎤
  94. ⎢ ⎥
  95. ⎣ⅈ⋅sin(χ)⋅cos(ψ) + sin(ψ)⋅cos(χ) ⎦
  96. Horizontal polarization.
  97. >>> pprint(jones_vector(0, 0), use_unicode=True)
  98. ⎡1⎤
  99. ⎢ ⎥
  100. ⎣0⎦
  101. Vertical polarization.
  102. >>> pprint(jones_vector(pi/2, 0), use_unicode=True)
  103. ⎡0⎤
  104. ⎢ ⎥
  105. ⎣1⎦
  106. Diagonal polarization.
  107. >>> pprint(jones_vector(pi/4, 0), use_unicode=True)
  108. ⎡√2⎤
  109. ⎢──⎥
  110. ⎢2 ⎥
  111. ⎢ ⎥
  112. ⎢√2⎥
  113. ⎢──⎥
  114. ⎣2 ⎦
  115. Anti-diagonal polarization.
  116. >>> pprint(jones_vector(-pi/4, 0), use_unicode=True)
  117. ⎡ √2 ⎤
  118. ⎢ ── ⎥
  119. ⎢ 2 ⎥
  120. ⎢ ⎥
  121. ⎢-√2 ⎥
  122. ⎢────⎥
  123. ⎣ 2 ⎦
  124. Right-hand circular polarization.
  125. >>> pprint(jones_vector(0, pi/4), use_unicode=True)
  126. ⎡ √2 ⎤
  127. ⎢ ── ⎥
  128. ⎢ 2 ⎥
  129. ⎢ ⎥
  130. ⎢√2⋅ⅈ⎥
  131. ⎢────⎥
  132. ⎣ 2 ⎦
  133. Left-hand circular polarization.
  134. >>> pprint(jones_vector(0, -pi/4), use_unicode=True)
  135. ⎡ √2 ⎤
  136. ⎢ ── ⎥
  137. ⎢ 2 ⎥
  138. ⎢ ⎥
  139. ⎢-√2⋅ⅈ ⎥
  140. ⎢──────⎥
  141. ⎣ 2 ⎦
  142. """
  143. return Matrix([-I*sin(chi)*sin(psi) + cos(chi)*cos(psi),
  144. I*sin(chi)*cos(psi) + sin(psi)*cos(chi)])
  145. def stokes_vector(psi, chi, p=1, I=1):
  146. """A Stokes vector corresponding to a polarization ellipse with ``psi``
  147. tilt, and ``chi`` circularity.
  148. Parameters
  149. ==========
  150. ``psi`` : numeric type or SymPy Symbol
  151. The tilt of the polarization relative to the ``x`` axis.
  152. ``chi`` : numeric type or SymPy Symbol
  153. The angle adjacent to the mayor axis of the polarization ellipse.
  154. ``p`` : numeric type or SymPy Symbol
  155. The degree of polarization.
  156. ``I`` : numeric type or SymPy Symbol
  157. The intensity of the field.
  158. Returns
  159. =======
  160. Matrix :
  161. A Stokes vector.
  162. Examples
  163. ========
  164. The axes on the Poincaré sphere.
  165. >>> from sympy import pprint, symbols, pi
  166. >>> from sympy.physics.optics.polarization import stokes_vector
  167. >>> psi, chi, p, I = symbols("psi, chi, p, I", real=True)
  168. >>> pprint(stokes_vector(psi, chi, p, I), use_unicode=True)
  169. ⎡ I ⎤
  170. ⎢ ⎥
  171. ⎢I⋅p⋅cos(2⋅χ)⋅cos(2⋅ψ)⎥
  172. ⎢ ⎥
  173. ⎢I⋅p⋅sin(2⋅ψ)⋅cos(2⋅χ)⎥
  174. ⎢ ⎥
  175. ⎣ I⋅p⋅sin(2⋅χ) ⎦
  176. Horizontal polarization
  177. >>> pprint(stokes_vector(0, 0), use_unicode=True)
  178. ⎡1⎤
  179. ⎢ ⎥
  180. ⎢1⎥
  181. ⎢ ⎥
  182. ⎢0⎥
  183. ⎢ ⎥
  184. ⎣0⎦
  185. Vertical polarization
  186. >>> pprint(stokes_vector(pi/2, 0), use_unicode=True)
  187. ⎡1 ⎤
  188. ⎢ ⎥
  189. ⎢-1⎥
  190. ⎢ ⎥
  191. ⎢0 ⎥
  192. ⎢ ⎥
  193. ⎣0 ⎦
  194. Diagonal polarization
  195. >>> pprint(stokes_vector(pi/4, 0), use_unicode=True)
  196. ⎡1⎤
  197. ⎢ ⎥
  198. ⎢0⎥
  199. ⎢ ⎥
  200. ⎢1⎥
  201. ⎢ ⎥
  202. ⎣0⎦
  203. Anti-diagonal polarization
  204. >>> pprint(stokes_vector(-pi/4, 0), use_unicode=True)
  205. ⎡1 ⎤
  206. ⎢ ⎥
  207. ⎢0 ⎥
  208. ⎢ ⎥
  209. ⎢-1⎥
  210. ⎢ ⎥
  211. ⎣0 ⎦
  212. Right-hand circular polarization
  213. >>> pprint(stokes_vector(0, pi/4), use_unicode=True)
  214. ⎡1⎤
  215. ⎢ ⎥
  216. ⎢0⎥
  217. ⎢ ⎥
  218. ⎢0⎥
  219. ⎢ ⎥
  220. ⎣1⎦
  221. Left-hand circular polarization
  222. >>> pprint(stokes_vector(0, -pi/4), use_unicode=True)
  223. ⎡1 ⎤
  224. ⎢ ⎥
  225. ⎢0 ⎥
  226. ⎢ ⎥
  227. ⎢0 ⎥
  228. ⎢ ⎥
  229. ⎣-1⎦
  230. Unpolarized light
  231. >>> pprint(stokes_vector(0, 0, 0), use_unicode=True)
  232. ⎡1⎤
  233. ⎢ ⎥
  234. ⎢0⎥
  235. ⎢ ⎥
  236. ⎢0⎥
  237. ⎢ ⎥
  238. ⎣0⎦
  239. """
  240. S0 = I
  241. S1 = I*p*cos(2*psi)*cos(2*chi)
  242. S2 = I*p*sin(2*psi)*cos(2*chi)
  243. S3 = I*p*sin(2*chi)
  244. return Matrix([S0, S1, S2, S3])
  245. def jones_2_stokes(e):
  246. """Return the Stokes vector for a Jones vector `e`.
  247. Parameters
  248. ==========
  249. ``e`` : SymPy Matrix
  250. A Jones vector.
  251. Returns
  252. =======
  253. SymPy Matrix
  254. A Jones vector.
  255. Examples
  256. ========
  257. The axes on the Poincaré sphere.
  258. >>> from sympy import pprint, pi
  259. >>> from sympy.physics.optics.polarization import jones_vector
  260. >>> from sympy.physics.optics.polarization import jones_2_stokes
  261. >>> H = jones_vector(0, 0)
  262. >>> V = jones_vector(pi/2, 0)
  263. >>> D = jones_vector(pi/4, 0)
  264. >>> A = jones_vector(-pi/4, 0)
  265. >>> R = jones_vector(0, pi/4)
  266. >>> L = jones_vector(0, -pi/4)
  267. >>> pprint([jones_2_stokes(e) for e in [H, V, D, A, R, L]],
  268. ... use_unicode=True)
  269. ⎡⎡1⎤ ⎡1 ⎤ ⎡1⎤ ⎡1 ⎤ ⎡1⎤ ⎡1 ⎤⎤
  270. ⎢⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥⎥
  271. ⎢⎢1⎥ ⎢-1⎥ ⎢0⎥ ⎢0 ⎥ ⎢0⎥ ⎢0 ⎥⎥
  272. ⎢⎢ ⎥, ⎢ ⎥, ⎢ ⎥, ⎢ ⎥, ⎢ ⎥, ⎢ ⎥⎥
  273. ⎢⎢0⎥ ⎢0 ⎥ ⎢1⎥ ⎢-1⎥ ⎢0⎥ ⎢0 ⎥⎥
  274. ⎢⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥⎥
  275. ⎣⎣0⎦ ⎣0 ⎦ ⎣0⎦ ⎣0 ⎦ ⎣1⎦ ⎣-1⎦⎦
  276. """
  277. ex, ey = e
  278. return Matrix([Abs(ex)**2 + Abs(ey)**2,
  279. Abs(ex)**2 - Abs(ey)**2,
  280. 2*re(ex*ey.conjugate()),
  281. -2*im(ex*ey.conjugate())])
  282. def linear_polarizer(theta=0):
  283. """A linear polarizer Jones matrix with transmission axis at
  284. an angle ``theta``.
  285. Parameters
  286. ==========
  287. ``theta`` : numeric type or SymPy Symbol
  288. The angle of the transmission axis relative to the horizontal plane.
  289. Returns
  290. =======
  291. SymPy Matrix
  292. A Jones matrix representing the polarizer.
  293. Examples
  294. ========
  295. A generic polarizer.
  296. >>> from sympy import pprint, symbols
  297. >>> from sympy.physics.optics.polarization import linear_polarizer
  298. >>> theta = symbols("theta", real=True)
  299. >>> J = linear_polarizer(theta)
  300. >>> pprint(J, use_unicode=True)
  301. ⎡ 2 ⎤
  302. ⎢ cos (θ) sin(θ)⋅cos(θ)⎥
  303. ⎢ ⎥
  304. ⎢ 2 ⎥
  305. ⎣sin(θ)⋅cos(θ) sin (θ) ⎦
  306. """
  307. M = Matrix([[cos(theta)**2, sin(theta)*cos(theta)],
  308. [sin(theta)*cos(theta), sin(theta)**2]])
  309. return M
  310. def phase_retarder(theta=0, delta=0):
  311. """A phase retarder Jones matrix with retardance `delta` at angle `theta`.
  312. Parameters
  313. ==========
  314. ``theta`` : numeric type or SymPy Symbol
  315. The angle of the fast axis relative to the horizontal plane.
  316. ``delta`` : numeric type or SymPy Symbol
  317. The phase difference between the fast and slow axes of the
  318. transmitted light.
  319. Returns
  320. =======
  321. SymPy Matrix :
  322. A Jones matrix representing the retarder.
  323. Examples
  324. ========
  325. A generic retarder.
  326. >>> from sympy import pprint, symbols
  327. >>> from sympy.physics.optics.polarization import phase_retarder
  328. >>> theta, delta = symbols("theta, delta", real=True)
  329. >>> R = phase_retarder(theta, delta)
  330. >>> pprint(R, use_unicode=True)
  331. ⎡ -ⅈ⋅δ -ⅈ⋅δ ⎤
  332. ⎢ ───── ───── ⎥
  333. ⎢⎛ ⅈ⋅δ 2 2 ⎞ 2 ⎛ ⅈ⋅δ⎞ 2 ⎥
  334. ⎢⎝ℯ ⋅sin (θ) + cos (θ)⎠⋅ℯ ⎝1 - ℯ ⎠⋅ℯ ⋅sin(θ)⋅cos(θ)⎥
  335. ⎢ ⎥
  336. ⎢ -ⅈ⋅δ -ⅈ⋅δ ⎥
  337. ⎢ ───── ─────⎥
  338. ⎢⎛ ⅈ⋅δ⎞ 2 ⎛ ⅈ⋅δ 2 2 ⎞ 2 ⎥
  339. ⎣⎝1 - ℯ ⎠⋅ℯ ⋅sin(θ)⋅cos(θ) ⎝ℯ ⋅cos (θ) + sin (θ)⎠⋅ℯ ⎦
  340. """
  341. R = Matrix([[cos(theta)**2 + exp(I*delta)*sin(theta)**2,
  342. (1-exp(I*delta))*cos(theta)*sin(theta)],
  343. [(1-exp(I*delta))*cos(theta)*sin(theta),
  344. sin(theta)**2 + exp(I*delta)*cos(theta)**2]])
  345. return R*exp(-I*delta/2)
  346. def half_wave_retarder(theta):
  347. """A half-wave retarder Jones matrix at angle `theta`.
  348. Parameters
  349. ==========
  350. ``theta`` : numeric type or SymPy Symbol
  351. The angle of the fast axis relative to the horizontal plane.
  352. Returns
  353. =======
  354. SymPy Matrix
  355. A Jones matrix representing the retarder.
  356. Examples
  357. ========
  358. A generic half-wave plate.
  359. >>> from sympy import pprint, symbols
  360. >>> from sympy.physics.optics.polarization import half_wave_retarder
  361. >>> theta= symbols("theta", real=True)
  362. >>> HWP = half_wave_retarder(theta)
  363. >>> pprint(HWP, use_unicode=True)
  364. ⎡ ⎛ 2 2 ⎞ ⎤
  365. ⎢-ⅈ⋅⎝- sin (θ) + cos (θ)⎠ -2⋅ⅈ⋅sin(θ)⋅cos(θ) ⎥
  366. ⎢ ⎥
  367. ⎢ ⎛ 2 2 ⎞⎥
  368. ⎣ -2⋅ⅈ⋅sin(θ)⋅cos(θ) -ⅈ⋅⎝sin (θ) - cos (θ)⎠⎦
  369. """
  370. return phase_retarder(theta, pi)
  371. def quarter_wave_retarder(theta):
  372. """A quarter-wave retarder Jones matrix at angle `theta`.
  373. Parameters
  374. ==========
  375. ``theta`` : numeric type or SymPy Symbol
  376. The angle of the fast axis relative to the horizontal plane.
  377. Returns
  378. =======
  379. SymPy Matrix
  380. A Jones matrix representing the retarder.
  381. Examples
  382. ========
  383. A generic quarter-wave plate.
  384. >>> from sympy import pprint, symbols
  385. >>> from sympy.physics.optics.polarization import quarter_wave_retarder
  386. >>> theta= symbols("theta", real=True)
  387. >>> QWP = quarter_wave_retarder(theta)
  388. >>> pprint(QWP, use_unicode=True)
  389. ⎡ -ⅈ⋅π -ⅈ⋅π ⎤
  390. ⎢ ───── ───── ⎥
  391. ⎢⎛ 2 2 ⎞ 4 4 ⎥
  392. ⎢⎝ⅈ⋅sin (θ) + cos (θ)⎠⋅ℯ (1 - ⅈ)⋅ℯ ⋅sin(θ)⋅cos(θ)⎥
  393. ⎢ ⎥
  394. ⎢ -ⅈ⋅π -ⅈ⋅π ⎥
  395. ⎢ ───── ─────⎥
  396. ⎢ 4 ⎛ 2 2 ⎞ 4 ⎥
  397. ⎣(1 - ⅈ)⋅ℯ ⋅sin(θ)⋅cos(θ) ⎝sin (θ) + ⅈ⋅cos (θ)⎠⋅ℯ ⎦
  398. """
  399. return phase_retarder(theta, pi/2)
  400. def transmissive_filter(T):
  401. """An attenuator Jones matrix with transmittance `T`.
  402. Parameters
  403. ==========
  404. ``T`` : numeric type or SymPy Symbol
  405. The transmittance of the attenuator.
  406. Returns
  407. =======
  408. SymPy Matrix
  409. A Jones matrix representing the filter.
  410. Examples
  411. ========
  412. A generic filter.
  413. >>> from sympy import pprint, symbols
  414. >>> from sympy.physics.optics.polarization import transmissive_filter
  415. >>> T = symbols("T", real=True)
  416. >>> NDF = transmissive_filter(T)
  417. >>> pprint(NDF, use_unicode=True)
  418. ⎡√T 0 ⎤
  419. ⎢ ⎥
  420. ⎣0 √T⎦
  421. """
  422. return Matrix([[sqrt(T), 0], [0, sqrt(T)]])
  423. def reflective_filter(R):
  424. """A reflective filter Jones matrix with reflectance `R`.
  425. Parameters
  426. ==========
  427. ``R`` : numeric type or SymPy Symbol
  428. The reflectance of the filter.
  429. Returns
  430. =======
  431. SymPy Matrix
  432. A Jones matrix representing the filter.
  433. Examples
  434. ========
  435. A generic filter.
  436. >>> from sympy import pprint, symbols
  437. >>> from sympy.physics.optics.polarization import reflective_filter
  438. >>> R = symbols("R", real=True)
  439. >>> pprint(reflective_filter(R), use_unicode=True)
  440. ⎡√R 0 ⎤
  441. ⎢ ⎥
  442. ⎣0 -√R⎦
  443. """
  444. return Matrix([[sqrt(R), 0], [0, -sqrt(R)]])
  445. def mueller_matrix(J):
  446. """The Mueller matrix corresponding to Jones matrix `J`.
  447. Parameters
  448. ==========
  449. ``J`` : SymPy Matrix
  450. A Jones matrix.
  451. Returns
  452. =======
  453. SymPy Matrix
  454. The corresponding Mueller matrix.
  455. Examples
  456. ========
  457. Generic optical components.
  458. >>> from sympy import pprint, symbols
  459. >>> from sympy.physics.optics.polarization import (mueller_matrix,
  460. ... linear_polarizer, half_wave_retarder, quarter_wave_retarder)
  461. >>> theta = symbols("theta", real=True)
  462. A linear_polarizer
  463. >>> pprint(mueller_matrix(linear_polarizer(theta)), use_unicode=True)
  464. ⎡ cos(2⋅θ) sin(2⋅θ) ⎤
  465. ⎢ 1/2 ──────── ──────── 0⎥
  466. ⎢ 2 2 ⎥
  467. ⎢ ⎥
  468. ⎢cos(2⋅θ) cos(4⋅θ) 1 sin(4⋅θ) ⎥
  469. ⎢──────── ──────── + ─ ──────── 0⎥
  470. ⎢ 2 4 4 4 ⎥
  471. ⎢ ⎥
  472. ⎢sin(2⋅θ) sin(4⋅θ) 1 cos(4⋅θ) ⎥
  473. ⎢──────── ──────── ─ - ──────── 0⎥
  474. ⎢ 2 4 4 4 ⎥
  475. ⎢ ⎥
  476. ⎣ 0 0 0 0⎦
  477. A half-wave plate
  478. >>> pprint(mueller_matrix(half_wave_retarder(theta)), use_unicode=True)
  479. ⎡1 0 0 0 ⎤
  480. ⎢ ⎥
  481. ⎢ 4 2 ⎥
  482. ⎢0 8⋅sin (θ) - 8⋅sin (θ) + 1 sin(4⋅θ) 0 ⎥
  483. ⎢ ⎥
  484. ⎢ 4 2 ⎥
  485. ⎢0 sin(4⋅θ) - 8⋅sin (θ) + 8⋅sin (θ) - 1 0 ⎥
  486. ⎢ ⎥
  487. ⎣0 0 0 -1⎦
  488. A quarter-wave plate
  489. >>> pprint(mueller_matrix(quarter_wave_retarder(theta)), use_unicode=True)
  490. ⎡1 0 0 0 ⎤
  491. ⎢ ⎥
  492. ⎢ cos(4⋅θ) 1 sin(4⋅θ) ⎥
  493. ⎢0 ──────── + ─ ──────── -sin(2⋅θ)⎥
  494. ⎢ 2 2 2 ⎥
  495. ⎢ ⎥
  496. ⎢ sin(4⋅θ) 1 cos(4⋅θ) ⎥
  497. ⎢0 ──────── ─ - ──────── cos(2⋅θ) ⎥
  498. ⎢ 2 2 2 ⎥
  499. ⎢ ⎥
  500. ⎣0 sin(2⋅θ) -cos(2⋅θ) 0 ⎦
  501. """
  502. A = Matrix([[1, 0, 0, 1],
  503. [1, 0, 0, -1],
  504. [0, 1, 1, 0],
  505. [0, -I, I, 0]])
  506. return simplify(A*TensorProduct(J, J.conjugate())*A.inv())
  507. def polarizing_beam_splitter(Tp=1, Rs=1, Ts=0, Rp=0, phia=0, phib=0):
  508. r"""A polarizing beam splitter Jones matrix at angle `theta`.
  509. Parameters
  510. ==========
  511. ``J`` : SymPy Matrix
  512. A Jones matrix.
  513. ``Tp`` : numeric type or SymPy Symbol
  514. The transmissivity of the P-polarized component.
  515. ``Rs`` : numeric type or SymPy Symbol
  516. The reflectivity of the S-polarized component.
  517. ``Ts`` : numeric type or SymPy Symbol
  518. The transmissivity of the S-polarized component.
  519. ``Rp`` : numeric type or SymPy Symbol
  520. The reflectivity of the P-polarized component.
  521. ``phia`` : numeric type or SymPy Symbol
  522. The phase difference between transmitted and reflected component for
  523. output mode a.
  524. ``phib`` : numeric type or SymPy Symbol
  525. The phase difference between transmitted and reflected component for
  526. output mode b.
  527. Returns
  528. =======
  529. SymPy Matrix
  530. A 4x4 matrix representing the PBS. This matrix acts on a 4x1 vector
  531. whose first two entries are the Jones vector on one of the PBS ports,
  532. and the last two entries the Jones vector on the other port.
  533. Examples
  534. ========
  535. Generic polarizing beam-splitter.
  536. >>> from sympy import pprint, symbols
  537. >>> from sympy.physics.optics.polarization import polarizing_beam_splitter
  538. >>> Ts, Rs, Tp, Rp = symbols(r"Ts, Rs, Tp, Rp", positive=True)
  539. >>> phia, phib = symbols("phi_a, phi_b", real=True)
  540. >>> PBS = polarizing_beam_splitter(Tp, Rs, Ts, Rp, phia, phib)
  541. >>> pprint(PBS, use_unicode=False)
  542. [ ____ ____ ]
  543. [ \/ Tp 0 I*\/ Rp 0 ]
  544. [ ]
  545. [ ____ ____ I*phi_a]
  546. [ 0 \/ Ts 0 -I*\/ Rs *e ]
  547. [ ]
  548. [ ____ ____ ]
  549. [I*\/ Rp 0 \/ Tp 0 ]
  550. [ ]
  551. [ ____ I*phi_b ____ ]
  552. [ 0 -I*\/ Rs *e 0 \/ Ts ]
  553. """
  554. PBS = Matrix([[sqrt(Tp), 0, I*sqrt(Rp), 0],
  555. [0, sqrt(Ts), 0, -I*sqrt(Rs)*exp(I*phia)],
  556. [I*sqrt(Rp), 0, sqrt(Tp), 0],
  557. [0, -I*sqrt(Rs)*exp(I*phib), 0, sqrt(Ts)]])
  558. return PBS