Merge branch 'main' of https://whale.am28.uni-tuebingen.de/git/Awendt/pyrelacs
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
from PyQt6.QtGui import QAction
|
||||
import sys
|
||||
import pathlib
|
||||
import ctypes
|
||||
|
||||
from PyQt6.QtCore import QProcess, QSize, QThreadPool, Qt, QSettings
|
||||
from PyQt6.QtWidgets import (
|
||||
@@ -13,13 +12,14 @@ from PyQt6.QtWidgets import (
|
||||
QMainWindow,
|
||||
QPlainTextEdit,
|
||||
)
|
||||
import tomli
|
||||
import uldaq
|
||||
from IPython import embed
|
||||
import numpy as np
|
||||
|
||||
from pyrelacs.util.logging import config_logging
|
||||
import pyrelacs.info as info
|
||||
from pyrelacs.worker import Worker
|
||||
from pyrelacs.repros.repros import Repro
|
||||
|
||||
log = config_logging()
|
||||
|
||||
@@ -31,8 +31,7 @@ class PyRelacs(QMainWindow):
|
||||
self.setMinimumSize(1000, 1000)
|
||||
|
||||
self.threadpool = QThreadPool()
|
||||
# for starting a Qprocess
|
||||
self.p = None
|
||||
self.repros = Repro()
|
||||
|
||||
self.daq_connect_button = QPushButton("Connect Daq")
|
||||
self.daq_connect_button.setCheckable(True)
|
||||
@@ -52,7 +51,7 @@ class PyRelacs(QMainWindow):
|
||||
|
||||
self.toolbar = QToolBar("Repros")
|
||||
self.addToolBar(self.toolbar)
|
||||
self.repro()
|
||||
self.repros_to_toolbar()
|
||||
|
||||
self.setFixedSize(QSize(400, 300))
|
||||
widget = QWidget()
|
||||
@@ -82,60 +81,18 @@ class PyRelacs(QMainWindow):
|
||||
except AttributeError:
|
||||
log.debug("DAQ was not connected")
|
||||
|
||||
def repro(self):
|
||||
repos_path = pathlib.Path(__file__).parent / "repros"
|
||||
repos_names = list(repos_path.glob("*.py"))
|
||||
# exclude the repos.py file
|
||||
repos_names = [
|
||||
f.with_suffix("").name for f in repos_names if not f.name == "repos.py"
|
||||
]
|
||||
for rep in repos_names:
|
||||
def repros_to_toolbar(self):
|
||||
repro_names, file_names = self.repros.names_of_repros()
|
||||
for rep, fn in zip(repro_names, file_names):
|
||||
individual_repro_button = QAction(rep, self)
|
||||
individual_repro_button.setStatusTip("Button")
|
||||
individual_repro_button.triggered.connect(
|
||||
lambda checked, n=rep: self.run_repro(n)
|
||||
lambda checked, n=rep, f=fn: self.run_repro(n, f)
|
||||
)
|
||||
self.toolbar.addAction(individual_repro_button)
|
||||
|
||||
def message(self, s):
|
||||
self.text.appendPlainText(s)
|
||||
|
||||
def run_repro(self, name_of_repo):
|
||||
if self.p is None:
|
||||
self.message(f"Executing process {name_of_repo}")
|
||||
self.p = QProcess()
|
||||
self.p.setWorkingDirectory(str(pathlib.Path(__file__).parent / "repros/"))
|
||||
# log.debug(pathlib.Path(__file__).parent / "repos")
|
||||
self.p.readyReadStandardOutput.connect(self.handle_stdout)
|
||||
self.p.readyReadStandardError.connect(self.handle_stderr)
|
||||
self.p.stateChanged.connect(self.handle_state)
|
||||
self.p.finished.connect(self.process_finished)
|
||||
self.p.start("python3", [f"{name_of_repo}" + ".py"])
|
||||
|
||||
def handle_stderr(self):
|
||||
if self.p is not None:
|
||||
data = self.p.readAllStandardError()
|
||||
stderr = bytes(data).decode("utf8")
|
||||
self.message(stderr)
|
||||
|
||||
def handle_stdout(self):
|
||||
if self.p is not None:
|
||||
data = self.p.readAllStandardOutput()
|
||||
stdout = bytes(data).decode("utf8")
|
||||
self.message(stdout)
|
||||
|
||||
def handle_state(self, state):
|
||||
states = {
|
||||
QProcess.ProcessState.NotRunning: "Not running",
|
||||
QProcess.ProcessState.Starting: "Starting",
|
||||
QProcess.ProcessState.Running: "Running",
|
||||
}
|
||||
state_name = states[state]
|
||||
self.message(f"State changed: {state_name}")
|
||||
|
||||
def process_finished(self):
|
||||
self.text.appendPlainText("Process finished")
|
||||
self.p = None
|
||||
def run_repro(self, n, fn):
|
||||
self.text.appendPlainText(f"started Repro {n}, {fn}")
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -19,7 +19,11 @@ class MccDac:
|
||||
log.error("Did not found daq devices, please connect one")
|
||||
exit(1)
|
||||
self.daq_device = uldaq.DaqDevice(devices[0])
|
||||
self.daq_device.connect()
|
||||
try:
|
||||
self.daq_device.connect()
|
||||
except uldaq.ul_exception.ULException:
|
||||
self.disconnect_dac()
|
||||
self.connect_dac()
|
||||
self.ai_device = self.daq_device.get_ai_device()
|
||||
self.ao_device = self.daq_device.get_ao_device()
|
||||
self.dio_device = self.daq_device.get_dio_device()
|
||||
@@ -85,8 +89,8 @@ class MccDac:
|
||||
|
||||
buffer = c_double * len(data)
|
||||
data_analog_output = buffer(*data)
|
||||
|
||||
log.debug(f"Created C_double data {data_analog_output}")
|
||||
|
||||
try:
|
||||
err = self.ao_device.a_out_scan(
|
||||
channels[0],
|
||||
@@ -123,12 +127,13 @@ class MccDac:
|
||||
self.disconnect_dac()
|
||||
|
||||
def diggital_trigger(self) -> None:
|
||||
if not self.read_bit(channel=0):
|
||||
self.write_bit(channel=0, bit=1)
|
||||
else:
|
||||
data = self.read_bit(channel=0)
|
||||
if data:
|
||||
self.write_bit(channel=0, bit=0)
|
||||
time.time_ns()
|
||||
self.write_bit(channel=0, bit=1)
|
||||
else:
|
||||
self.write_bit(channel=0, bit=1)
|
||||
|
||||
def write_bit(self, channel: int = 0, bit: int = 1) -> None:
|
||||
self.dio_device.d_config_bit(
|
||||
@@ -266,7 +271,7 @@ class MccDac:
|
||||
log.info("Muting channel one")
|
||||
binary_db2 = "00000000"
|
||||
|
||||
channels_db = binary_db1 + binary_db2
|
||||
channels_db = binary_db2 + binary_db1
|
||||
self.write_bit(channel=4, bit=0)
|
||||
for b in channels_db:
|
||||
self.write_bit(channel=5, bit=int(b))
|
||||
0
pyrelacs/repros/__init__.py
Normal file
0
pyrelacs/repros/__init__.py
Normal file
@@ -1,14 +1,16 @@
|
||||
import ctypes
|
||||
import signal
|
||||
import sys
|
||||
import faulthandler
|
||||
|
||||
import time
|
||||
|
||||
import uldaq
|
||||
from IPython import embed
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy.signal import welch, csd
|
||||
from scipy.signal import find_peaks
|
||||
|
||||
from pyrelacs.repros.mccdac import MccDac
|
||||
from pyrelacs.devices.mccdac import MccDac
|
||||
from pyrelacs.util.logging import config_logging
|
||||
|
||||
log = config_logging()
|
||||
@@ -18,50 +20,232 @@ faulthandler.enable()
|
||||
class Calibration(MccDac):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.SAMPLERATE = 40_000.0
|
||||
self.DURATION = 5
|
||||
self.AMPLITUDE = 1
|
||||
self.SINFREQ = 750
|
||||
|
||||
def run(self):
|
||||
|
||||
def segfault_handler(self, signum, frame):
|
||||
print(f"Segmentation fault caught! Signal number: {signum}")
|
||||
self.disconnect_dac()
|
||||
sys.exit(1) # Gracefully exit the program
|
||||
|
||||
def check_amplitude(self):
|
||||
db_values = [0.0, -5.0, -10.0, -20.0, -50.0]
|
||||
colors = ["red", "green", "blue", "black", "yellow"]
|
||||
self.set_attenuation_level(db_channel1=0.0, db_channel2=0.0)
|
||||
# write to ananlog 1
|
||||
t = np.arange(0, DURATION, 1 / SAMPLERATE)
|
||||
data = AMPLITUDE * np.sin(2 * np.pi * SINFREQ * t)
|
||||
data_channels = np.zeros(2 * len(data))
|
||||
# c = [(i,for i,j in zip(data, data)]
|
||||
t = np.arange(0, self.DURATION, 1 / self.SAMPLERATE)
|
||||
data = self.AMPLITUDE * np.sin(2 * np.pi * self.SINFREQ * t)
|
||||
fig, ax = plt.subplots()
|
||||
|
||||
stim = self.write_analog(
|
||||
data,
|
||||
[0, 0],
|
||||
SAMPLERATE,
|
||||
ScanOption=uldaq.ScanOption.EXTTRIGGER,
|
||||
)
|
||||
data_channel_one = self.read_analog(
|
||||
[0, 0], DURATION, SAMPLERATE, ScanOption=uldaq.ScanOption.EXTTRIGGER
|
||||
)
|
||||
time.sleep(1)
|
||||
for i, db_value in enumerate(db_values):
|
||||
self.set_attenuation_level(db_channel1=db_value, db_channel2=db_value)
|
||||
log.debug(f"{db_value}")
|
||||
|
||||
self.diggital_trigger()
|
||||
stim = self.write_analog(
|
||||
data,
|
||||
[0, 0],
|
||||
self.SAMPLERATE,
|
||||
ScanOption=uldaq.ScanOption.EXTTRIGGER,
|
||||
)
|
||||
|
||||
try:
|
||||
self.ai_device.scan_wait(uldaq.WaitType.WAIT_UNTIL_DONE, 15)
|
||||
self.write_bit(channel=0, bit=0)
|
||||
data_channel_one = self.read_analog(
|
||||
[0, 0], self.DURATION, self.SAMPLERATE, ScanOption=uldaq.ScanOption.EXTTRIGGER
|
||||
)
|
||||
time.sleep(1)
|
||||
self.set_analog_to_zero()
|
||||
except uldaq.ul_exception.ULException:
|
||||
log.debug("Operation timed out")
|
||||
# reset the diggital trigger
|
||||
|
||||
log.debug("Starting the Scan")
|
||||
self.diggital_trigger()
|
||||
|
||||
try:
|
||||
self.ao_device.scan_wait(uldaq.WaitType.WAIT_UNTIL_DONE, 15)
|
||||
log.debug("Scan finished")
|
||||
self.write_bit(channel=0, bit=0)
|
||||
time.sleep(1)
|
||||
self.set_analog_to_zero()
|
||||
except uldaq.ul_exception.ULException:
|
||||
log.debug("Operation timed out")
|
||||
# reset the diggital trigger
|
||||
self.write_bit(channel=0, bit=0)
|
||||
time.sleep(1)
|
||||
self.set_analog_to_zero()
|
||||
self.disconnect_dac()
|
||||
|
||||
if i == 0:
|
||||
ax.plot(t, stim, label=f"Input_{db_value}", color=colors[i])
|
||||
ax.plot(t, data_channel_one, label=f"Reaout {db_value}", color=colors[i])
|
||||
|
||||
ax.legend()
|
||||
plt.show()
|
||||
|
||||
self.disconnect_dac()
|
||||
|
||||
def check_beat(self):
|
||||
self.set_attenuation_level(db_channel1=-10.0, db_channel2=0.0)
|
||||
t = np.arange(0, self.DURATION, 1 / self.SAMPLERATE)
|
||||
data = self.AMPLITUDE * np.sin(2 * np.pi * self.SINFREQ * t)
|
||||
# data = np.concatenate((data, data))
|
||||
db_values = [0.0, -5.0, -8.5, -10.0]
|
||||
colors = ["red", "blue", "black", "green"]
|
||||
colors_in = ["lightcoral", "lightblue", "grey", "lightgreen"]
|
||||
fig, axes = plt.subplots(2, 2, sharex="col")
|
||||
for i, db_value in enumerate(db_values):
|
||||
self.set_attenuation_level(db_channel1=db_value)
|
||||
stim = self.write_analog(
|
||||
data,
|
||||
[0, 0],
|
||||
self.SAMPLERATE,
|
||||
ScanOption=uldaq.ScanOption.EXTTRIGGER,
|
||||
)
|
||||
readout = self.read_analog(
|
||||
[0, 1],
|
||||
self.DURATION,
|
||||
self.SAMPLERATE,
|
||||
ScanOption=uldaq.ScanOption.EXTTRIGGER,
|
||||
)
|
||||
self.diggital_trigger()
|
||||
signal.signal(signal.SIGSEGV, self.segfault_handler)
|
||||
log.info(self.ao_device)
|
||||
ai_status = uldaq.ScanStatus.RUNNING
|
||||
ao_status = uldaq.ScanStatus.RUNNING
|
||||
|
||||
log.debug(
|
||||
f"Status Analog_output {ao_status}\n, Status Analog_input {ai_status}"
|
||||
)
|
||||
while (ai_status != uldaq.ScanStatus.IDLE) and (
|
||||
ao_status != uldaq.ScanStatus.IDLE
|
||||
):
|
||||
# log.debug("Scanning")
|
||||
time.time_ns()
|
||||
ai_status = self.ai_device.get_scan_status()[0]
|
||||
ao_status = self.ao_device.get_scan_status()[0]
|
||||
|
||||
self.write_bit(channel=0, bit=0)
|
||||
time.sleep(1)
|
||||
self.set_analog_to_zero()
|
||||
self.disconnect_dac()
|
||||
embed()
|
||||
exit()
|
||||
log.debug(
|
||||
f"Status Analog_output {ao_status}\n, Status Analog_input {ai_status}"
|
||||
)
|
||||
channel1 = np.array(readout[::2])
|
||||
channel2 = np.array(readout[1::2])
|
||||
beat = channel1 + channel2
|
||||
beat_square = beat**2
|
||||
|
||||
f, powerspec = welch(beat, fs=self.SAMPLERATE)
|
||||
powerspec = decibel(powerspec)
|
||||
|
||||
f_sq, powerspec_sq = welch(beat_square, fs=self.SAMPLERATE)
|
||||
powerspec_sq = decibel(powerspec_sq)
|
||||
peaks = find_peaks(powerspec_sq, prominence=20)[0]
|
||||
|
||||
f_stim, powerspec_stim = welch(channel1, fs=self.SAMPLERATE)
|
||||
powerspec_stim = decibel(powerspec_stim)
|
||||
|
||||
f_in, powerspec_in = welch(channel2, fs=self.SAMPLERATE)
|
||||
powerspec_in = decibel(powerspec_in)
|
||||
|
||||
axes[0, 0].plot(
|
||||
t,
|
||||
channel1,
|
||||
label=f"{db_value} Readout Channel0",
|
||||
color=colors[i],
|
||||
)
|
||||
axes[0, 0].plot(
|
||||
t,
|
||||
channel2,
|
||||
label=f"{db_value} Readout Channel1",
|
||||
color=colors_in[i],
|
||||
)
|
||||
|
||||
axes[0, 1].plot(
|
||||
f_stim,
|
||||
powerspec_stim,
|
||||
label=f"{db_value} powerspec Channel0",
|
||||
color=colors[i],
|
||||
)
|
||||
axes[0, 1].plot(
|
||||
f_in,
|
||||
powerspec_in,
|
||||
label=f"{db_value} powerspec Channel2",
|
||||
color=colors_in[i],
|
||||
)
|
||||
axes[0, 1].set_xlabel("Freq [HZ]")
|
||||
axes[0, 1].set_ylabel("dB")
|
||||
|
||||
axes[1, 0].plot(
|
||||
t,
|
||||
beat,
|
||||
label="Beat",
|
||||
color=colors[i],
|
||||
)
|
||||
axes[1, 0].plot(
|
||||
t,
|
||||
beat**2,
|
||||
label="Beat squared",
|
||||
color=colors_in[i],
|
||||
)
|
||||
axes[1, 0].legend()
|
||||
|
||||
axes[1, 1].plot(
|
||||
f,
|
||||
powerspec,
|
||||
color=colors[i],
|
||||
)
|
||||
axes[1, 1].plot(
|
||||
f_sq,
|
||||
powerspec_sq,
|
||||
color=colors_in[i],
|
||||
label=f"dB {db_value}, first peak {np.min(f_sq[peaks])}",
|
||||
)
|
||||
axes[1, 1].scatter(
|
||||
f_sq[peaks],
|
||||
powerspec_sq[peaks],
|
||||
color="maroon",
|
||||
)
|
||||
axes[1, 1].set_xlabel("Freq [HZ]")
|
||||
axes[1, 1].set_ylabel("dB")
|
||||
axes[0, 0].legend()
|
||||
axes[1, 1].legend()
|
||||
plt.show()
|
||||
self.set_analog_to_zero()
|
||||
self.disconnect_dac()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
SAMPLERATE = 40_000.0
|
||||
DURATION = 5
|
||||
AMPLITUDE = 0.5
|
||||
SINFREQ = 10
|
||||
def decibel(power, ref_power=1.0, min_power=1e-20):
|
||||
"""Transform power to decibel relative to ref_power.
|
||||
|
||||
cal = Calibration()
|
||||
# cal.ccheck_attenuator()
|
||||
cal.check_amplitude()
|
||||
\\[ decibel = 10 \\cdot \\log_{10}(power/ref\\_power) \\]
|
||||
Power values smaller than `min_power` are set to `-np.inf`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
power: float or array
|
||||
Power values, for example from a power spectrum or spectrogram.
|
||||
ref_power: float or None or 'peak'
|
||||
Reference power for computing decibel.
|
||||
If set to `None` or 'peak', the maximum power is used.
|
||||
min_power: float
|
||||
Power values smaller than `min_power` are set to `-np.inf`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
decibel_psd: array
|
||||
Power values in decibel relative to `ref_power`.
|
||||
"""
|
||||
if np.isscalar(power):
|
||||
tmp_power = np.array([power])
|
||||
decibel_psd = np.array([power])
|
||||
else:
|
||||
tmp_power = power
|
||||
decibel_psd = power.copy()
|
||||
if ref_power is None or ref_power == "peak":
|
||||
ref_power = np.max(decibel_psd)
|
||||
decibel_psd[tmp_power <= min_power] = float("-inf")
|
||||
decibel_psd[tmp_power > min_power] = 10.0 * np.log10(
|
||||
decibel_psd[tmp_power > min_power] / ref_power
|
||||
)
|
||||
if np.isscalar(power):
|
||||
return decibel_psd[0]
|
||||
else:
|
||||
return decibel_psd
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
import ctypes
|
||||
|
||||
import uldaq
|
||||
from IPython import embed
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
|
||||
from pyrelacs.util.logging import config_logging
|
||||
|
||||
log = config_logging()
|
||||
|
||||
|
||||
class ReadWrite:
|
||||
def __init__(self) -> None:
|
||||
devices = uldaq.get_daq_device_inventory(uldaq.InterfaceType.USB)
|
||||
log.debug(f"Found daq devices {len(devices)}, connecting to the first one")
|
||||
self.daq_device = uldaq.DaqDevice(devices[0])
|
||||
self.daq_device.connect()
|
||||
log.debug("Connected")
|
||||
# self.daq_device.enable_event(
|
||||
# uldaq.DaqEventType.ON_DATA_AVAILABLE,
|
||||
# 1,
|
||||
# self.read_write,
|
||||
# (uldaq.DaqEventType.ON_DATA_AVAILABLE, 1, 1),
|
||||
# )
|
||||
|
||||
def read_write(self) -> None:
|
||||
# event_type = callback_args.event_type
|
||||
# event_data = callback_args.event_data
|
||||
# user_data = callback_args.user_data
|
||||
|
||||
FS = 30_000.0
|
||||
DURATION = 10
|
||||
FREQUENCY = 100
|
||||
|
||||
time = np.arange(0, DURATION, 1 / FS)
|
||||
data = 2 * np.sin(2 * np.pi * FREQUENCY * time)
|
||||
|
||||
buffer = ctypes.c_double * len(time)
|
||||
data_c = buffer(*data)
|
||||
buf = uldaq.create_float_buffer(1, len(time))
|
||||
|
||||
# Get the Ananlog In device and Analog Info
|
||||
ai_device = self.daq_device.get_ai_device()
|
||||
ai_info = ai_device.get_info()
|
||||
|
||||
# Get the Analog Out device
|
||||
ao_device = self.daq_device.get_ao_device()
|
||||
ao_info = ao_device.get_info()
|
||||
|
||||
er_ao = ao_device.a_out_scan(
|
||||
0,
|
||||
0,
|
||||
uldaq.Range.BIP10VOLTS,
|
||||
int(len(data)),
|
||||
30_000.0,
|
||||
uldaq.ScanOption.DEFAULTIO,
|
||||
uldaq.AOutScanFlag.DEFAULT,
|
||||
data_c,
|
||||
)
|
||||
|
||||
er_ai = ai_device.a_in_scan(
|
||||
1,
|
||||
1,
|
||||
uldaq.AiInputMode.SINGLE_ENDED,
|
||||
uldaq.Range.BIP10VOLTS,
|
||||
len(time),
|
||||
FS,
|
||||
uldaq.ScanOption.DEFAULTIO,
|
||||
uldaq.AInScanFlag.DEFAULT,
|
||||
data=buf,
|
||||
)
|
||||
ai_device.scan_wait(uldaq.WaitType.WAIT_UNTIL_DONE, timeout=-1)
|
||||
log.debug("Scanning")
|
||||
|
||||
self.daq_device.disconnect()
|
||||
self.daq_device.release()
|
||||
plt.plot(buf)
|
||||
plt.plot(data_c)
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
daq_input = ReadWrite()
|
||||
daq_input.read_write()
|
||||
@@ -1,28 +0,0 @@
|
||||
import uldaq
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from pyrelacs.util.logging import config_logging
|
||||
from .repos import MccDac
|
||||
|
||||
log = config_logging()
|
||||
|
||||
|
||||
class ReadData(MccDac):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def analog_in(self) -> None:
|
||||
# Get the Ananlog In device and Analog Info
|
||||
data = self.read_analog_daq(
|
||||
[0, 0],
|
||||
10,
|
||||
3000.0,
|
||||
)
|
||||
plt.plot(data)
|
||||
plt.show()
|
||||
self.disconnect_dac()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
daq_input = ReadData()
|
||||
daq_input.analog_in()
|
||||
@@ -1,28 +0,0 @@
|
||||
import ctypes
|
||||
|
||||
import uldaq
|
||||
from IPython import embed
|
||||
from pyrelacs.repros.repos import MccDac
|
||||
from pyrelacs.util.logging import config_logging
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
log = config_logging()
|
||||
|
||||
|
||||
class Output_daq(MccDac):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def write_daq(self):
|
||||
log.debug("running repro")
|
||||
time = np.arange(0, 10, 1 / 30_000.0)
|
||||
data = 1 * np.sin(2 * np.pi * 1 * time)
|
||||
self.write_analog(data, [0, 0], 30_000, ScanOption=uldaq.ScanOption.EXTTRIGGER)
|
||||
self.diggital_trigger()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
daq_input = Output_daq()
|
||||
daq_input.write_daq()
|
||||
# daq_input.trigger()
|
||||
33
pyrelacs/repros/repros.py
Normal file
33
pyrelacs/repros/repros.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import ast
|
||||
import pathlib
|
||||
|
||||
from IPython import embed
|
||||
|
||||
|
||||
class Repro:
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
def run_repro(self, name: str, *args, **kwargs) -> None:
|
||||
pass
|
||||
|
||||
def names_of_repros(self):
|
||||
file_path_cur = pathlib.Path(__file__).parent
|
||||
python_files = list(file_path_cur.glob("**/*.py"))
|
||||
exclude_files = ["repros.py", "__init__.py"]
|
||||
python_files = [f for f in python_files if f.name not in exclude_files]
|
||||
repro_names = []
|
||||
file_names = []
|
||||
for python_file in python_files:
|
||||
with open(python_file, "r") as file:
|
||||
file_content = file.read()
|
||||
tree = ast.parse(file_content)
|
||||
class_name = [
|
||||
node.name
|
||||
for node in ast.walk(tree)
|
||||
if isinstance(node, ast.ClassDef)
|
||||
]
|
||||
repro_names.extend(class_name)
|
||||
file_names.append(python_file)
|
||||
file.close()
|
||||
return repro_names, file_names
|
||||
75
pyrelacs/worker.py
Normal file
75
pyrelacs/worker.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from PyQt6.QtCore import QRunnable, pyqtSlot, QObject, pyqtSignal
|
||||
|
||||
|
||||
class WorkerSignals(QObject):
|
||||
"""
|
||||
Defines the signals available from a running worker thread.
|
||||
|
||||
Supported signals are:
|
||||
|
||||
finished
|
||||
No data
|
||||
|
||||
error
|
||||
tuple (exctype, value, traceback.format_exc() )
|
||||
|
||||
result
|
||||
object data returned from processing, anything
|
||||
|
||||
progress
|
||||
int indicating % progress
|
||||
|
||||
"""
|
||||
|
||||
finished = pyqtSignal()
|
||||
error = pyqtSignal(tuple)
|
||||
result = pyqtSignal(object)
|
||||
progress = pyqtSignal(int)
|
||||
|
||||
|
||||
class Worker(QRunnable):
|
||||
"""
|
||||
Worker thread
|
||||
|
||||
Inherits from QRunnable to handler worker thread setup, signals and wrap-up.
|
||||
|
||||
:param callback: The function callback to run on this worker thread. Supplied args and
|
||||
kwargs will be passed through to the runner.
|
||||
:type callback: function
|
||||
:param args: Arguments to pass to the callback function
|
||||
:param kwargs: Keywords to pass to the callback function
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, fn, *args, **kwargs):
|
||||
super(Worker, self).__init__()
|
||||
|
||||
# Store constructor arguments (re-used for processing)
|
||||
self.fn = fn
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.signals = WorkerSignals()
|
||||
|
||||
# Add the callback to our kwargs
|
||||
self.kwargs["progress_callback"] = self.signals.progress
|
||||
|
||||
@pyqtSlot()
|
||||
def run(self):
|
||||
"""
|
||||
Initialise the runner function with passed args, kwargs.
|
||||
"""
|
||||
|
||||
# Retrieve args/kwargs here; and fire processing using them
|
||||
try:
|
||||
result = self.fn(*self.args, **self.kwargs)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
exctype, value = sys.exc_info()[:2]
|
||||
self.signals.error.emit((exctype, value, traceback.format_exc()))
|
||||
else:
|
||||
self.signals.result.emit(result) # Return the result of the processing
|
||||
finally:
|
||||
self.signals.finished.emit() # Done
|
||||
Reference in New Issue
Block a user