195 lines
7.5 KiB
Python
195 lines
7.5 KiB
Python
from zipfile import stringFileHeader
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
if __package__ is None:
|
|
# make relative imports work as described here: https://peps.python.org/pep-0366/#proposed-change
|
|
__package__ = "photoreflectance"
|
|
from os import path
|
|
filepath = path.realpath(path.abspath(__file__))
|
|
sys.path.insert(0, 'C:\\Users\Administrator\Desktop\Software\Python\Python\github')
|
|
|
|
from time import sleep
|
|
|
|
import numpy as np
|
|
import scipy as scp
|
|
from Bentham import Bentham
|
|
from devices.Xenon import Xenon
|
|
from devices.Shutter import ShutterProbe
|
|
|
|
from .update_funcs import Monitor
|
|
from .measurement_device.impl.sr830 import SR830
|
|
from .measurement_device.impl.model7260 import Model7260
|
|
import logging
|
|
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format="%(asctime)s [%(levelname)s] [%(name)s] %(message)s",
|
|
handlers=[
|
|
# logging.FileHandler(log_path),
|
|
logging.StreamHandler()
|
|
]
|
|
)
|
|
|
|
|
|
def _measure_both(monochromator: Bentham, lockin: SR830, shutter: ShutterProbe, wl_range=(400, 750, 25), AC=True, DC=True, monitor=None):
|
|
mon = monitor if monitor is not None else Monitor(r"$\lambda$ [nm]", [
|
|
# dict(ax=0, ylabel="Wavelength [nm]", color="red"),
|
|
# dict(ax=1, ylabel="Ref", color="blue", lim=(0, 5)),
|
|
dict(ax=0, ylabel=r"$\Delta R$", color="green"),
|
|
dict(ax=1, ylabel=r"$\sigma_{\Delta R}$", color="green"),
|
|
dict(ax=2, ylabel=r"$R$", color="blue"),
|
|
dict(ax=3, ylabel=r"$\sigma_R$", color="blue"),
|
|
dict(ax=4, ylabel=r"$\Delta R/R$", color="red"),
|
|
# dict(ax=3, ylabel="R", color="blue"),
|
|
dict(ax=5, ylabel="Phase", color="orange", lim=(-180, 180))
|
|
])
|
|
N_bins = 512
|
|
shutter.open_()
|
|
data_raw = []
|
|
data_wl = {}
|
|
sample_rate = 512
|
|
timeout_s = 60
|
|
timeout_interval = 0.5
|
|
lockin.run("SENS 17") # 1 mV/nA
|
|
# lockin.run("OFLT 5") # 3 ms
|
|
# since we dont expect changes in our signal, we can use large time constants and aggresive filter slope
|
|
# for better signal to noise
|
|
lockin.run("OFLT 8") # 100 ms
|
|
lockin.run("OFSL 3") # 24dB/Oct ms
|
|
if AC:
|
|
input("Plug the detector into lock-in port 'A/I' (front panel) and press enter > ")
|
|
input("Make sure the laser is turned on and press enter > ")
|
|
for i_wl, wl in enumerate(range(*wl_range)):
|
|
lockin.buffer_setup(CH1="R", CH2="Theta", length=N_bins, sample_rate=sample_rate)
|
|
monochromator.drive(wl)
|
|
sleep(1.5) # need to wait until lock-in R signal is stable
|
|
lockin.buffer_start_fill()
|
|
t = timeout_s
|
|
while t > 0:
|
|
t -= timeout_interval
|
|
sleep(timeout_interval)
|
|
if lockin.buffer_is_done():
|
|
break
|
|
if t < 0: raise RuntimeError("Timed out waiting for buffer measurement to finish")
|
|
arr = lockin.buffer_get_data(CH1=True, CH2=True)
|
|
data_raw.append([wl, arr])
|
|
arr[1] += 180
|
|
# calculate means, for theta use circular mean
|
|
dR = np.mean(arr[0,:])
|
|
sdR = np.std(arr[0,:])
|
|
theta = scp.stats.circmean(arr[1,:], low=-180, high=180)
|
|
stheta = scp.stats.circstd(arr[1,:], low=-180, high=180)
|
|
data_wl[wl] = {"dR": dR, "Theta": theta, "sdR": sdR, "sTheta": stheta}
|
|
# wl - dR, sdR, R, sR, dR/R, Theta
|
|
mon.update(wl, dR, sdR, None, None, None, stheta)
|
|
if DC:
|
|
input("Turn off the laser and press enter > ")
|
|
input("Plug the detector into lock-in port 'Aux In 1' (rear panel) and press enter > ")
|
|
for i_wl, wl in enumerate(range(*wl_range)):
|
|
lockin.buffer_setup(CH1="Aux In 1", CH2="Theta", length=N_bins, sample_rate=sample_rate)
|
|
monochromator.drive(wl)
|
|
sleep(0.5)
|
|
lockin.buffer_start_fill()
|
|
t = timeout_s
|
|
while t > 0:
|
|
t -= timeout_interval
|
|
sleep(timeout_interval)
|
|
if lockin.buffer_is_done():
|
|
break
|
|
if t < 0: raise RuntimeError("Timed out waiting for buffer measurement to finish")
|
|
arr = lockin.buffer_get_data(CH1=True, CH2=False)
|
|
if AC:
|
|
data_raw[i_wl].append(arr)
|
|
else:
|
|
data_raw.append([wl, arr])
|
|
means = np.mean(arr, axis=1)
|
|
errs = np.std(arr, axis=1)
|
|
if not wl in data_wl: data_wl[wl] = {}
|
|
data_wl[wl] |= {"R": means[0], "sR": errs[0]}
|
|
# wl - dR, sdR, R, sR, dR/R, Theta
|
|
if AC:
|
|
dR_R = data_wl[wl]["dR"] / data_wl[wl]["R"]
|
|
mon.override(wl, None, None, data_wl[wl]["R"], data_wl[wl]["sR"], dR_R, None)
|
|
else:
|
|
mon.update(wl, None, None, data_wl[wl]["R"], data_wl[wl]["sR"], None, None)
|
|
return data_wl, data_raw, mon
|
|
|
|
|
|
def _measure(monochromator: Bentham, lamp: Xenon, lockin: SR830, shutter: ShutterProbe, wl_range=(400, 750, 25)):
|
|
data = []
|
|
mon = Monitor(r"$\lambda$ [nm]", [
|
|
# dict(ax=0, ylabel="Wavelength [nm]", color="red"),
|
|
# dict(ax=1, ylabel="Ref", color="blue", lim=(0, 5)),
|
|
dict(ax=0, ylabel=r"$\Delta R$", color="green"),
|
|
dict(ax=1, ylabel=r"$\sigma_{\Delta R}$", color="green"),
|
|
# dict(ax=3, ylabel="R", color="blue"),
|
|
dict(ax=2, ylabel="Phase", color="orange", lim=(-180, 180))
|
|
|
|
])
|
|
N_bins = 100
|
|
dt = 0.01
|
|
i = 0
|
|
shutter.open_()
|
|
if isinstance(lockin, SR830):
|
|
lockin.run("SENS 17") # 1 mV/nA
|
|
lockin.run("OFLT 5")
|
|
for wl in range(*wl_range):
|
|
arr = np.empty((N_bins, 2))
|
|
monochromator.drive(wl)
|
|
|
|
# lockin.auto_gain()
|
|
for j in range(N_bins):
|
|
dR, theta = lockin.snap(what="3,4")
|
|
arr[j,:] = (dR, theta)
|
|
i += 1
|
|
# sleep(dt)
|
|
means = np.mean(arr, axis=0)
|
|
errs = np.std(arr, axis=0)
|
|
mon.update(wl, means[0], errs[0], means[1])
|
|
data.append((wl, arr))
|
|
elif isinstance(lockin, Model7260):
|
|
# lockin.run("SEN 21") # 10 mV/nA
|
|
lockin.run("SEN 24") # 100 mV/nA
|
|
for wl in range(*wl_range):
|
|
monochromator.drive(wl)
|
|
|
|
lockin.buffer_setup(MAG=1, PHASE=1, ADC1=1, ADC2=1, interval_ms=5, length=1000)
|
|
lockin.buffer_start_fill()
|
|
timeout_s = 60
|
|
timeout_interval = 0.5
|
|
while timeout_s > 0:
|
|
timeout_s -= timeout_interval
|
|
sleep(timeout_interval)
|
|
if lockin.buffer_is_done():
|
|
break
|
|
arr = lockin.buffer_get_data()
|
|
length = arr.shape[0]
|
|
# for j in range(length):
|
|
# # wl, ref, dR, R, theta
|
|
# mon.update(i*length+j, wl, arr[j][3], arr[j][0], arr[j][2], arr[j][1])
|
|
mon.update_array(range(i * length, (i+1)*length), [wl for _ in range(length)], arr[:,3], arr[:,0], arr[:,2], arr[:,1])
|
|
data.append((wl, arr))
|
|
i += 1
|
|
|
|
shutter.close_()
|
|
return data, mon
|
|
|
|
lockin = None
|
|
lamp = None
|
|
mcm = None
|
|
shutter = None
|
|
|
|
def measure(wl_range=(400, 500, 2)):
|
|
return _measure(mcm, lamp, lockin, shutter, wl_range=wl_range)
|
|
|
|
def measure_both(**kwargs):
|
|
return _measure_both(mcm, lockin, shutter, **kwargs)
|
|
|
|
if __name__ == "__main__":
|
|
mcm = Bentham()
|
|
# mcm.park()
|
|
lamp = Xenon()
|
|
lockin = SR830.connect_device(SR830.enumerate_devices()[0])
|
|
# lockin = Model7260.connect_device(Model7260.enumerate_devices()[0])
|
|
shutter = ShutterProbe() |