summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2019-05-03 20:22:46 +0200
committerPaweł Redman <pawel.redman@gmail.com>2019-05-03 20:26:15 +0200
commitd10f88b9e6119d223b6712eb0eb4f1365cf6c66d (patch)
tree641d25b5bc59de8df54e10e68cf06604bb50c260
parentca5b42577795d63e6e59bde31698edb5443b85e8 (diff)
Stokes parameters
-rw-r--r--src/phys.py24
-rw-r--r--src/ui.py38
-rw-r--r--src/ui_table.py56
3 files changed, 81 insertions, 37 deletions
diff --git a/src/phys.py b/src/phys.py
index 4e78fe2..c47a497 100644
--- a/src/phys.py
+++ b/src/phys.py
@@ -7,6 +7,16 @@ from PyQt5.QtCore import *
from ui import *
+
+
+def jones_to_stokes(E):
+ I = np.abs(E[0] ** 2) + np.abs(E[1] ** 2)
+ Q = np.abs(E[0] ** 2) - np.abs(E[1] ** 2)
+ U = 2 * np.real(E[0] * np.conjugate(E[1]))
+ V = 2 * np.imag(E[0] * np.conjugate(E[1]))
+ return np.array([I, Q, U, V])
+
+
def R(theta):
return np.array([[np.cos(theta), np.sin(theta)],
[-np.sin(theta), np.cos(theta)]])
@@ -14,7 +24,6 @@ def R(theta):
class Ellipse:
def __init__(self, state):
- # FIXME: a less brute-force way of doing this
if state is None:
self.alpha = np.nan
self.theta = np.nan
@@ -44,12 +53,14 @@ class Ellipse:
bounds=[0, np.pi], method="bounded")
self.a = r(opt.x)
- self.alpha = angle(x(opt.x))
+ V = jones_to_stokes(state)
+
+ self.alpha = np.arctan2(V[2], V[1]) / 2
+ if self.alpha < 0:
+ self.alpha += np.pi
- self.e = self.b / self.a
- self.theta = np.arctan(self.e)
- if self.alpha > angle(x(opt.x + 0.001)):
- self.theta *= -1
+ R = np.sqrt(V[1] ** 2 + V[2] ** 2 + V[3] ** 2)
+ self.theta = np.arcsin(V[3] / R) / 2
class Polarizer:
def __init__(self, type, delta=0):
@@ -98,6 +109,7 @@ class System:
def recalculate(system):
system.states = [None] * len(system.elements)
+ system.Vs = [None] * len(system.elements)
system.ellipses = list()
state = None
diff --git a/src/ui.py b/src/ui.py
index fc85dbd..60f2fac 100644
--- a/src/ui.py
+++ b/src/ui.py
@@ -32,38 +32,42 @@ def update():
for i, pol in enumerate(system.elements):
row = GUI.table.rows[i]
- # update all the diagrams
row.ellipse.state = system.states[i]
row.ellipse.ellipse = system.ellipses[i]
row.ellipse.is_used = system.elements[i].enable
row.ellipse.repaint()
-
- text = "%s at %f°" \
- % (pol.type, (pol.angle + pol.delta) * 180 / np.pi)
- row.info_angle.setText(text)
state = system.states[i]
+ V = system.Vs[i]
ellipse = system.ellipses[i]
if state is None:
- I = 1
- row.info_jones.setText("Unpolarized")
+ I = system.input_intensity
+
+ for label in row.jones:
+ label.setText("-")
+ row.stokes[0].setText("%g" % I)
+ for label in row.stokes[1:]:
+ label.setText("0")
else:
I = np.abs(state[0] * state[0].conjugate() \
+ state[1] * state[1].conjugate())
if state is None:
continue
-
- A, B = state
- text = "I = %f\n" % I
- text += "%f ∠ %+f°\n%f ∠ %+f°\n" % \
- (np.abs(A), 180 / np.pi * np.angle(A), \
- np.abs(B), 180 / np.pi * np.angle(B))
- text += "α = %f°\nφ = %+f°" % \
- (180 / np.pi * ellipse.alpha, 180 / np.pi * ellipse.theta)
- text = text.replace("-", "- ").replace("+", "+ ")
- row.info_jones.setText(text)
+
+ polar = [(np.abs(z), np.angle(z) * 180 / np.pi) for z in state]
+ for i, (a, b) in enumerate(polar):
+ row.jones[2 * i].setText("%g" % a)
+ row.jones[2 * i + 1].setText("%g°" % b)
+
+ delta = polar[1][1] - polar[0][1]
+ row.jones[4].setText("%g°" % delta)
+
+ for i, x in enumerate(phys.jones_to_stokes(state)):
+ row.stokes[i].setText("%g" % x)
+ row.stokes[4].setText("%g°" % (ellipse.alpha * 180 / np.pi))
+ row.stokes[5].setText("%g°" % (ellipse.theta * 180 / np.pi))
GUI.widok.intensity = I
GUI.widok.repaint()
diff --git a/src/ui_table.py b/src/ui_table.py
index 8286f5e..52a4171 100644
--- a/src/ui_table.py
+++ b/src/ui_table.py
@@ -147,7 +147,7 @@ class OptBox(QVBoxLayout):
def change_enable(self):
self.row.pol.enable = self.enable.isChecked()
- update()
+ GUI.do_update()
@@ -161,22 +161,49 @@ class SystemTableRow:
self.delta = pol.delta
self.ref = pol.ref
+ # Option box (column 1)
self.optbox = OptBox(self, pol)
parent.setCellWidget(row_number, 0, LayoutWrapper(self.optbox))
+ # Ellipse diagram (column 2)
self.ellipse = EllipseWidget(pol)
parent.setCellWidget(row_number, 1, self.ellipse)
- self.info = QVBoxLayout()
- self.info_angle = MeinLabel()
- self.info_angle.setAlignment(Qt.AlignLeft)
- self.info.addWidget(self.info_angle)
- self.info.addWidget(QLabel("Polarization state"))
- self.info_jones = MeinLabel()
- self.info_jones.setAlignment(Qt.AlignLeft)
- self.info.addWidget(self.info_jones)
- self.info.addItem(ExpandingSpacer())
- parent.setCellWidget(row_number, 2, LayoutWrapper(self.info))
+ # Jones vector (column 3)
+ box = QVBoxLayout()
+ parent.setCellWidget(row_number, 2, LayoutWrapper(box))
+
+ grid = QGridLayout()
+ grid.setColumnStretch(2, 10)
+ box.addLayout(grid)
+ box.addItem(ExpandingSpacer())
+
+ for i, label in enumerate(["|Ex|", "arg Ex", "|Ey|", "arg Ey", "δ"]):
+ grid.addWidget(QLabel(label), 1 + i, 1)
+
+ self.jones = list()
+ for i in range(5):
+ label = MeinLabel("-")
+ grid.addWidget(label, 1 + i, 2)
+ self.jones.append(label)
+
+ # Stokes parameters (column 4)
+ box = QVBoxLayout()
+ parent.setCellWidget(row_number, 3, LayoutWrapper(box))
+
+ grid = QGridLayout()
+ grid.setColumnStretch(2, 10)
+ box.addLayout(grid)
+ box.addItem(ExpandingSpacer())
+
+ for i, label in enumerate(["I", "Q", "U", "V", "α", "θ"]):
+ grid.addWidget(QLabel(label), 1 + i, 1)
+
+ self.stokes = list()
+ for i in range(6):
+ label = MeinLabel("-")
+ grid.addWidget(label, 1 + i, 2)
+ self.stokes.append(label)
def angle_change(self):
self.angle = self.optbox.angle.angle / 180 * np.pi
@@ -190,14 +217,15 @@ class SystemTable(QTableWidget):
super().__init__()
self.rows = list()
- self.setColumnCount(3) # this won't change
+ self.setColumnCount(4) # this won't change
self.hh = self.horizontalHeader()
self.hh.setSectionResizeMode(0, QHeaderView.ResizeToContents)
- self.hh.resizeSection(1, 170)
+ self.hh.resizeSection(1, 150)
+ self.hh.resizeSection(2, 150)
self.hh.setStretchLastSection(True)
self.setHorizontalHeaderLabels([
- "Settings", "Ellipse", "State"
+ "Settings", "Diagram", "State", "Stokes"
])
self.vh = self.verticalHeader()