11 Commits

Author SHA1 Message Date
wendtalexander
8f6c9b1e5e [ui/structure] updating repros to tab bar with individual plots and nix blocks 2024-10-23 11:09:44 +02:00
wendtalexander
574e9a8110 [ui/plots] fixing error if nothing has been plotted, the gui could not close 2024-10-23 11:08:54 +02:00
wendtalexander
75619cf1c8 [repro/class] provides with repros with args and kwargs 2024-10-23 11:07:55 +02:00
wendtalexander
02911e57f8 [repros] moving to sperate folders 2024-10-23 11:07:19 +02:00
wendtalexander
557535ffa4 [repros] moving to sperate folder, writing run method 2024-10-23 11:06:51 +02:00
wendtalexander
110629dae0 [calibration] moving calibration to own folder, rewriting run method 2024-10-23 11:06:26 +02:00
wendtalexander
7c4b5098c1 [mccdaq] printing exception error 2024-10-23 11:05:41 +02:00
wendtalexander
e2b7ed3a61 [ui] creates a nix file with pressing the record button 2024-10-22 10:11:07 +02:00
wendtalexander
038327bfeb [ui/continously] updating plot to plot the last chunk 2024-10-22 10:10:40 +02:00
wendtalexander
4f7ebbe8c3 [dataio/nix] adding mutex, writing data_array, and the last chunk 2024-10-22 10:10:09 +02:00
wendtalexander
12e82dceee [dataio] adding time sleep for performance 2024-10-21 17:44:02 +02:00
9 changed files with 304 additions and 96 deletions

View File

@@ -1,5 +1,6 @@
import time import time
from IPython import embed from IPython import embed
from PyQt6.QtCore import QMutex
import nixio import nixio
from pyrelacs.dataio.circbuffer import CircBuffer from pyrelacs.dataio.circbuffer import CircBuffer
@@ -12,30 +13,53 @@ class NixWriter:
def __init__(self, buffer: CircBuffer) -> None: def __init__(self, buffer: CircBuffer) -> None:
self.buffer = buffer self.buffer = buffer
def write_nix(self, *args, **kwargs): def write_nix(
self._write_header() self,
items = 0 data_array: nixio.DataArray,
chunk = 1000 mutex: QMutex,
channel: int = 0,
chunk_size=1000,
*args,
**kwargs,
):
index = 0
log.debug("Starting the writing") log.debug("Starting the writing")
self.write = True self.write = True
total_count = self.buffer.totalcount()
while self.write: while self.write:
if total_count - items >= chunk: total_count = self.buffer.totalcount(channel=channel)
log.debug(items) if total_count - index >= chunk_size:
mutex.lock()
log.debug(index)
try: try:
data, _ = self.buffer.read(items, extend=chunk) _, data = self.buffer.read(
self.data_array.append(data) index, extend=chunk_size, channel=channel
)
if index == 0:
data_array.write_direct(data)
else:
data_array.append(data)
index += chunk_size
except IndexError as e: except IndexError as e:
time.sleep(0.01) time.sleep(0.001)
log.debug(f"{e}") log.debug(f"{e}")
items += chunk mutex.unlock()
else: else:
time.sleep(0.01) time.sleep(0.001)
continue continue
total_count = self.buffer.totalcount(channel=channel)
try:
mutex.lock()
_, data = self.buffer.read(
index, extend=total_count - index, channel=channel
)
data_array.append(data)
mutex.unlock()
index += total_count - index
except IndexError as e:
log.error(f"Could not read the last samples, {e}")
log.debug("Stoppint the writing") log.debug("Stoppint the writing")
log.debug(f"Samples written {items}") log.debug(f"Samples written {index}")
self.nix_file.close()
def _write_header(self): def _write_header(self):
self.nix_file = nixio.File.open(path="data.nix", mode=nixio.FileMode.Overwrite) self.nix_file = nixio.File.open(path="data.nix", mode=nixio.FileMode.Overwrite)

View File

@@ -224,10 +224,10 @@ class MccDaq:
uldaq.AOutListFlag.DEFAULT, uldaq.AOutListFlag.DEFAULT,
[0, 0], [0, 0],
) )
except Exception as e: except Exception as er:
log.error("f{e}") log.error(f"{er}")
log.error("disconnection dac") log.error("disconnection dac")
self.disconnect_daq() # self.disconnect_daq()
def digital_trigger(self, ch: int = 0) -> None: def digital_trigger(self, ch: int = 0) -> None:
""" """

View File

@@ -6,6 +6,8 @@ import uldaq
from IPython import embed from IPython import embed
import numpy as np import numpy as np
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from scipy.signal import welch, find_peaks
import pyqtgraph as pg
from pyrelacs.devices.mccdaq import MccDaq from pyrelacs.devices.mccdaq import MccDaq
from pyrelacs.util.logging import config_logging from pyrelacs.util.logging import config_logging
@@ -15,40 +17,50 @@ log = config_logging()
faulthandler.enable() faulthandler.enable()
class Calibration(MccDaq): class Calibration:
def __init__(self) -> None: def __init__(self, config, mccdaq: MccDaq) -> None:
super().__init__() self.config = config
self.mccdaq = mccdaq
self.SAMPLERATE = 40_000.0 self.SAMPLERATE = 40_000.0
self.DURATION = 5 self.DURATION = 5
self.AMPLITUDE = 1 self.AMPLITUDE = 1
self.SINFREQ = 750 self.SINFREQ = 750
@staticmethod @staticmethod
def run(nix_file: nix.File): def run(*args, **kwargs):
calb = Calibration() nix_block = args[0]
calb.check_beat(nix_file) figure = args[1]
mccdaq = args[2]
config = args[3]
calb = Calibration(config, mccdaq)
calb.check_beat(nix_block)
calb.plot(figure, nix_block)
return "finished"
def check_amplitude(self): def check_amplitude(self):
db_values = [0.0, -5.0, -10.0, -20.0, -50.0] db_values = [0.0, -5.0, -10.0, -20.0, -50.0]
colors = ["red", "green", "blue", "black", "yellow"] colors = ["red", "green", "blue", "black", "yellow"]
self.set_attenuation_level(db_channel1=0.0, db_channel2=0.0) self.mccdaq.set_attenuation_level(db_channel1=0.0, db_channel2=0.0)
# write to ananlog 1 # write to ananlog 1
t = np.arange(0, self.DURATION, 1 / self.SAMPLERATE) t = np.arange(0, self.DURATION, 1 / self.SAMPLERATE)
data = self.AMPLITUDE * np.sin(2 * np.pi * self.SINFREQ * t) data = self.AMPLITUDE * np.sin(2 * np.pi * self.SINFREQ * t)
fig, ax = plt.subplots() fig, ax = plt.subplots()
for i, db_value in enumerate(db_values): for i, db_value in enumerate(db_values):
self.set_attenuation_level(db_channel1=db_value, db_channel2=db_value) self.mccdaq.set_attenuation_level(
db_channel1=db_value, db_channel2=db_value
)
log.debug(f"{db_value}") log.debug(f"{db_value}")
stim = self.write_analog( stim = self.mccdaq.write_analog(
data, data,
[0, 0], [0, 0],
self.SAMPLERATE, self.SAMPLERATE,
ScanOption=uldaq.ScanOption.EXTTRIGGER, ScanOption=uldaq.ScanOption.EXTTRIGGER,
) )
data_channel_one = self.read_analog( data_channel_one = self.mccdaq.read_analog(
[0, 0], [0, 0],
self.DURATION, self.DURATION,
self.SAMPLERATE, self.SAMPLERATE,
@@ -57,21 +69,21 @@ class Calibration(MccDaq):
time.sleep(1) time.sleep(1)
log.debug("Starting the Scan") log.debug("Starting the Scan")
self.digital_trigger() self.mccdaq.digital_trigger()
try: try:
self.ao_device.scan_wait(uldaq.WaitType.WAIT_UNTIL_DONE, 15) self.mccdaq.ao_device.scan_wait(uldaq.WaitType.WAIT_UNTIL_DONE, 15)
log.debug("Scan finished") log.debug("Scan finished")
self.write_bit(channel=0, bit=0) self.mccdaq.write_bit(channel=0, bit=0)
time.sleep(1) time.sleep(1)
self.set_analog_to_zero() self.mccdaq.set_analog_to_zero()
except uldaq.ul_exception.ULException: except uldaq.ul_exception.ULException:
log.debug("Operation timed out") log.debug("Operation timed out")
# reset the diggital trigger # reset the diggital trigger
self.write_bit(channel=0, bit=0) self.mccdaq.write_bit(channel=0, bit=0)
time.sleep(1) time.sleep(1)
self.set_analog_to_zero() self.mccdaq.set_analog_to_zero()
self.disconnect_daq() # self.mccdaq.disconnect_daq()
if i == 0: if i == 0:
ax.plot(t, stim, label=f"Input_{db_value}", color=colors[i]) ax.plot(t, stim, label=f"Input_{db_value}", color=colors[i])
@@ -80,34 +92,33 @@ class Calibration(MccDaq):
ax.legend() ax.legend()
plt.show() plt.show()
self.disconnect_daq() # self.mccdaq.disconnect_daq()
def check_beat(self, nix_file: nix.File): def check_beat(self, nix_block: nix.Block):
self.set_attenuation_level(db_channel1=-10.0, db_channel2=0.0) self.mccdaq.set_attenuation_level(db_channel1=-10.0, db_channel2=0.0)
t = np.arange(0, self.DURATION, 1 / self.SAMPLERATE) t = np.arange(0, self.DURATION, 1 / self.SAMPLERATE)
data = self.AMPLITUDE * np.sin(2 * np.pi * self.SINFREQ * t) data = self.AMPLITUDE * np.sin(2 * np.pi * self.SINFREQ * t)
# data = np.concatenate((data, data)) # data = np.concatenate((data, data))
db_values = [0.0, -5.0, -8.5, -10.0] db_values = [0.0, -5.0, -8.5, -10.0]
colors = ["red", "blue", "black", "green"] colors = ["red", "blue", "black", "green"]
colors_in = ["lightcoral", "lightblue", "grey", "lightgreen"] colors_in = ["lightcoral", "lightblue", "grey", "lightgreen"]
block = nix_file.create_block("Calibration", "data")
# fig, axes = plt.subplots(2, 2, sharex="col") # fig, axes = plt.subplots(2, 2, sharex="col")
for i, db_value in enumerate(db_values): for i, db_value in enumerate(db_values):
self.set_attenuation_level(db_channel1=db_value) self.mccdaq.set_attenuation_level(db_channel1=db_value)
stim = self.write_analog( stim = self.mccdaq.write_analog(
data, data,
[0, 0], [0, 0],
self.SAMPLERATE, self.SAMPLERATE,
ScanOption=uldaq.ScanOption.EXTTRIGGER, ScanOption=uldaq.ScanOption.EXTTRIGGER,
) )
readout = self.read_analog( readout = self.mccdaq.read_analog(
[0, 1], [0, 1],
self.DURATION, self.DURATION,
self.SAMPLERATE, self.SAMPLERATE,
ScanOption=uldaq.ScanOption.EXTTRIGGER, ScanOption=uldaq.ScanOption.EXTTRIGGER,
) )
self.digital_trigger() self.mccdaq.digital_trigger()
log.info(self.ao_device) log.info(self.mccdaq.ao_device)
ai_status = uldaq.ScanStatus.RUNNING ai_status = uldaq.ScanStatus.RUNNING
ao_status = uldaq.ScanStatus.RUNNING ao_status = uldaq.ScanStatus.RUNNING
@@ -119,10 +130,10 @@ class Calibration(MccDaq):
): ):
# log.debug("Scanning") # log.debug("Scanning")
time.time_ns() time.time_ns()
ai_status = self.ai_device.get_scan_status()[0] ai_status = self.mccdaq.ai_device.get_scan_status()[0]
ao_status = self.ao_device.get_scan_status()[0] ao_status = self.mccdaq.ao_device.get_scan_status()[0]
self.write_bit(channel=0, bit=0) self.mccdaq.write_bit(channel=0, bit=0)
log.debug( log.debug(
f"Status Analog_output {ao_status}\n, Status Analog_input {ai_status}" f"Status Analog_output {ao_status}\n, Status Analog_input {ai_status}"
) )
@@ -130,7 +141,7 @@ class Calibration(MccDaq):
channel1 = np.array(readout[::2]) channel1 = np.array(readout[::2])
channel2 = np.array(readout[1::2]) channel2 = np.array(readout[1::2])
stim_data = block.create_data_array( stim_data = nix_block.create_data_array(
f"stimulus_{db_value}", f"stimulus_{db_value}",
"nix.regular_sampled", "nix.regular_sampled",
shape=data.shape, shape=data.shape,
@@ -143,7 +154,7 @@ class Calibration(MccDaq):
label="time", label="time",
unit="s", unit="s",
) )
fish_data = block.create_data_array( fish_data = nix_block.create_data_array(
f"fish_{db_value}", f"fish_{db_value}",
"Array", "Array",
shape=data.shape, shape=data.shape,
@@ -157,7 +168,72 @@ class Calibration(MccDaq):
unit="s", unit="s",
) )
self.set_analog_to_zero() time.time_ns()
self.mccdaq.set_analog_to_zero()
def plot(self, figure, block):
self.figure = figure
self.figure.setBackground("w")
self.beat_plot = self.figure.addPlot(row=0, col=0)
self.power_plot = self.figure.addPlot(row=1, col=0)
self.beat_plot.addLegend()
self.power_plot.addLegend()
# self.power_plot.setLogMode(x=False, y=True)
colors = ["red", "green", "blue", "black", "yellow"]
for i, (stim, fish) in enumerate(
zip(list(block.data_arrays)[::2], list(block.data_arrays)[1::2])
):
f_stim, stim_power = welch(
stim[:],
fs=40_000.0,
window="flattop",
nperseg=100_000,
)
stim_power = decibel(stim_power)
stim_max_power_index = np.argmax(stim_power)
freq_stim = f_stim[stim_max_power_index]
f_fish, fish_power = welch(
fish[:],
fs=40_000.0,
window="flattop",
nperseg=100_000,
)
fish_power = decibel(fish_power)
fish_max_power_index = np.argmax(fish_power)
freq_fish = f_fish[fish_max_power_index]
beat_frequency = np.abs(freq_fish - freq_stim)
beat = stim[:] + fish[:]
beat_squared = beat**2
f, powerspec = welch(
beat_squared,
window="flattop",
fs=40_000.0,
nperseg=100_000,
)
powerspec = decibel(powerspec)
padding = 20
integration_window = powerspec[
(f > beat_frequency - padding) & (f < beat_frequency + padding)
]
peaks = find_peaks(powerspec, prominence=40)[0]
pen = pg.mkPen(colors[i])
self.beat_plot.plot(
np.arange(0, len(beat)) / 40_000.0,
beat,
pen=pen,
name=stim.name,
)
self.power_plot.plot(f, powerspec, pen=pen, name=stim.name)
self.power_plot.plot(f[peaks], powerspec[peaks], pen=None, symbol="x")
def decibel(power, ref_power=1.0, min_power=1e-20): def decibel(power, ref_power=1.0, min_power=1e-20):

View File

View File

@@ -22,9 +22,7 @@ class Repro:
def __init__(self) -> None: def __init__(self) -> None:
pass pass
def run_repro( def run_repro(self, name: str, file: pathlib.Path, *args, **kwargs) -> None:
self, nix_file: nix.File, name: str, file: pathlib.Path, *args, **kwargs
) -> None:
spec = importlib.util.spec_from_file_location("rep", file) spec = importlib.util.spec_from_file_location("rep", file)
if not spec: if not spec:
log.error("Could not load the file") log.error("Could not load the file")
@@ -40,7 +38,7 @@ class Repro:
log.error(f"{spec.loader} is None") log.error(f"{spec.loader} is None")
if hasattr(module, name): if hasattr(module, name):
rep_class = getattr(module, name) rep_class = getattr(module, name)
rep_class.run(nix_file) rep_class.run(*args, **kwargs)
else: else:
raise AttributeError(f"{file.name} has no {name} class") raise AttributeError(f"{file.name} has no {name} class")

View File

@@ -1,3 +0,0 @@
class Sinus:
def __init__(self) -> None:
pass

View File

@@ -0,0 +1,17 @@
import nixio
from pyrelacs.util.logging import config_logging
log = config_logging()
class Sinus:
def __init__(self) -> None:
pass
@staticmethod
def run(config, mccdaq, nix_block: nixio.Block, figure) -> None:
log.debug(config)
log.debug(mccdaq)
log.debug(nix_block)
log.debug(figure)

View File

@@ -1,11 +1,16 @@
import time import time
from pathlib import Path as path from pathlib import Path as path
from datetime import datetime
from dataclasses import asdict
from PyQt6.QtGui import QAction, QIcon, QKeySequence from PyQt6.QtGui import QAction, QIcon, QKeySequence
from PyQt6.QtCore import Qt, QSize, QThreadPool, QMutex from PyQt6.QtCore import Qt, QSize, QThreadPool, QMutex
from PyQt6.QtWidgets import ( from PyQt6.QtWidgets import (
QGridLayout, QGridLayout,
QPushButton,
QTabWidget,
QToolBar, QToolBar,
QVBoxLayout,
QWidget, QWidget,
QMainWindow, QMainWindow,
QPlainTextEdit, QPlainTextEdit,
@@ -13,9 +18,8 @@ from PyQt6.QtWidgets import (
QStatusBar, QStatusBar,
) )
from pyqtgraph.Qt.QtCore import QThread
import uldaq import nixio
import nixio as nix
import pyqtgraph as pg import pyqtgraph as pg
import quantities as pq import quantities as pq
@@ -51,6 +55,8 @@ class PyRelacs(QMainWindow):
self.mccdaq = MccDaq() self.mccdaq = MccDaq()
end = time.time() end = time.time()
log.debug(f"Connection to DAQ took {end - start}") log.debug(f"Connection to DAQ took {end - start}")
else:
self.mccdaq = None
self.repros = Repro() self.repros = Repro()
@@ -59,6 +65,8 @@ class PyRelacs(QMainWindow):
) # Ensure icons are displayed with text ) # Ensure icons are displayed with text
self.setWindowTitle("PyRelacs") self.setWindowTitle("PyRelacs")
self.create_nix_file(f"{_root}/test.nix", self.config.metadata)
self.mutex = QMutex() self.mutex = QMutex()
self.figure = pg.GraphicsLayoutWidget() self.figure = pg.GraphicsLayoutWidget()
@@ -72,10 +80,13 @@ class PyRelacs(QMainWindow):
self.setStatusBar(QStatusBar(self)) self.setStatusBar(QStatusBar(self))
self.create_actions() self.create_actions()
self.create_toolbars() self.create_toolbars()
self.repro_tabs = QTabWidget()
self.create_repros_tabs()
layout = QGridLayout() layout = QGridLayout()
layout.addWidget(self.figure, 0, 0, 2, 2) layout.addWidget(self.figure, 0, 0, 2, 2)
layout.addWidget(self.text, 2, 0, 1, 2) layout.addWidget(self.repro_tabs, 2, 0, 2, 2)
layout.addWidget(self.text, 4, 0, 1, 1)
widget = QWidget() widget = QWidget()
widget.setLayout(layout) widget.setLayout(layout)
@@ -103,7 +114,7 @@ class PyRelacs(QMainWindow):
self.continously_plot = Continously(self.figure, self.buffer) self.continously_plot = Continously(self.figure, self.buffer)
# self.continously_plot.plot() # self.continously_plot.plot()
if self.config.settings.daq: if self.mccdaq:
log.debug("Creating Daq Generator") log.debug("Creating Daq Generator")
self.daq_producer = DaqProducer(self.buffer, self.mccdaq.daq_device, [1, 1]) self.daq_producer = DaqProducer(self.buffer, self.mccdaq.daq_device, [1, 1])
log.debug("Creating Sinus Generator") log.debug("Creating Sinus Generator")
@@ -125,7 +136,7 @@ class PyRelacs(QMainWindow):
self._daq_connectaction = QAction( self._daq_connectaction = QAction(
QIcon(":icons/connect.png"), "Connect DAQ", self QIcon(":icons/connect.png"), "Connect DAQ", self
) )
if self.config.settings.daq: if self.mccdaq:
self._daq_connectaction.setStatusTip("Connect to daq device") self._daq_connectaction.setStatusTip("Connect to daq device")
# self._daq_connectaction.setShortcut(QKeySequence("Alt+d")) # self._daq_connectaction.setShortcut(QKeySequence("Alt+d"))
self._daq_connectaction.triggered.connect(self.mccdaq.connect_dac) self._daq_connectaction.triggered.connect(self.mccdaq.connect_dac)
@@ -144,7 +155,7 @@ class PyRelacs(QMainWindow):
# # self._daq_calibaction.setShortcut(QKeySequence("Alt+d")) # # self._daq_calibaction.setShortcut(QKeySequence("Alt+d"))
# self._daq_calibaction.triggered.connect(self.calibration_plot.plot) # self._daq_calibaction.triggered.connect(self.calibration_plot.plot)
self._run_action = QAction(QIcon(":/icons/record.png"), "Run", self) self._run_action = QAction(QIcon(":/icons/record.png"), "RunDAQ", self)
self._run_action.triggered.connect(self.run_daq) self._run_action.triggered.connect(self.run_daq)
self._run_sinus_action = QAction(QIcon(":/icons/record.png"), "Sinus", self) self._run_sinus_action = QAction(QIcon(":/icons/record.png"), "Sinus", self)
@@ -209,18 +220,76 @@ class PyRelacs(QMainWindow):
daq_toolbar.addAction(self._record) daq_toolbar.addAction(self._record)
self.addToolBar(Qt.ToolBarArea.TopToolBarArea, daq_toolbar) self.addToolBar(Qt.ToolBarArea.TopToolBarArea, daq_toolbar)
repro_toolbar = QToolBar("Repros") def create_repros_tabs(self):
repro_names, file_names = self.repros.names_of_repros( repro_names, file_names = self.repros.names_of_repros(
include_repros=self.config.settings.repros include_repros=self.config.settings.repros
) )
nix_blocks = {
rep: self.nix_file.create_block(f"{rep}", "Data Repro")
for rep in repro_names
}
figures_repros = {rep: pg.GraphicsLayoutWidget() for rep in repro_names}
for rep, fn in zip(repro_names, file_names): for rep, fn in zip(repro_names, file_names):
repro_action = QAction(rep, self) tab = QWidget()
repro_action.setStatusTip(rep) tab_layout = QGridLayout()
repro_action.triggered.connect(
lambda checked, n=rep, f=fn: self.run_repro(n, f) run_repro_button = QPushButton(f"Run {rep}")
run_repro_button.setCheckable(True)
run_repro_button.clicked.connect(
lambda checked, n=rep, f=fn: self.run_repro(
n,
f,
nix_blocks,
figures_repros,
self.mccdaq,
self.config,
)
) )
repro_toolbar.addAction(repro_action) tab_layout.addWidget(run_repro_button, 0, 0, 1, 0)
self.addToolBar(Qt.ToolBarArea.BottomToolBarArea, repro_toolbar) tab_layout.addWidget(figures_repros[rep], 1, 0, 1, 1)
tab.setLayout(tab_layout)
self.repro_tabs.addTab(tab, f"{rep}")
def run_repro(
self,
name_of_repro: str,
file_of_repro: str,
nix_block,
figures,
*args,
):
self.text.appendPlainText(f"started Repro {name_of_repro}, {file_of_repro}")
nix_block_repro = nix_block[name_of_repro]
figure_repro = figures[name_of_repro]
worker = Worker(
self.repros.run_repro,
name_of_repro,
file_of_repro,
nix_block_repro,
figure_repro,
*args[-2:],
)
worker.signals.result.connect(self.print_output)
worker.signals.finished.connect(self.thread_complete)
worker.signals.progress.connect(self.progress_fn)
self.threadpool.start(worker)
def create_nix_file(self, file_path, metadata):
self.nix_file = nixio.File.open(
path=f"{file_path}", mode=nixio.FileMode.Overwrite
)
self.block = self.nix_file.create_block("recording", "testfile")
self.section = self.nix_file.create_section("metadata", "config.yaml")
for key, value in asdict(metadata).items():
self.section[key] = value
self.data_array_analog1 = self.block.create_data_array(
"Analog1", "ndarray", shape=(1000,), dtype=nixio.DataType.Double
)
self.data_array_analog2 = self.block.create_data_array(
"Analog2", "ndarray", shape=(1000,), dtype=nixio.DataType.Double
)
def recenter_continously_plot(self): def recenter_continously_plot(self):
self.continously_plot.refresh() self.continously_plot.refresh()
@@ -251,12 +320,33 @@ class PyRelacs(QMainWindow):
self.continously_plot.plot() self.continously_plot.plot()
def record(self): def record(self):
nix_writer = Worker(self.nix_writer.write_nix) self.create_nix_file("test.nix", self.config.metadata)
log.debug("Created nix file")
nix_writer = Worker(
self.nix_writer.write_nix,
data_array=self.data_array_analog1,
mutex=self.mutex,
channel=0,
chunk_size=1000,
)
nix_writer.signals.result.connect(self.print_output) nix_writer.signals.result.connect(self.print_output)
nix_writer.signals.finished.connect(self.thread_complete) nix_writer.signals.finished.connect(self.thread_complete)
nix_writer.signals.progress.connect(self.progress_fn) nix_writer.signals.progress.connect(self.progress_fn)
self.threadpool.start(nix_writer) self.threadpool.start(nix_writer)
nix_writer2 = Worker(
self.nix_writer.write_nix,
data_array=self.data_array_analog2,
mutex=self.mutex,
channel=0,
chunk_size=1000,
)
nix_writer2.signals.result.connect(self.print_output)
nix_writer2.signals.finished.connect(self.thread_complete)
nix_writer2.signals.progress.connect(self.progress_fn)
self.threadpool.start(nix_writer2)
def stop_recording(self): def stop_recording(self):
self.add_to_textfield("Stopping the recording") self.add_to_textfield("Stopping the recording")
self.continously_plot.stop_plotting() self.continously_plot.stop_plotting()
@@ -273,15 +363,6 @@ class PyRelacs(QMainWindow):
log.debug("Stopping DAQ") log.debug("Stopping DAQ")
self.daq_producer.stop_aquisition() self.daq_producer.stop_aquisition()
def run_repro(self, n, fn):
self.text.appendPlainText(f"started Repro {n}, {fn}")
worker = Worker(self.repros.run_repro, self.nix_calibration, n, fn)
worker.signals.result.connect(self.print_output)
worker.signals.finished.connect(self.thread_complete)
worker.signals.progress.connect(self.progress_fn)
self.threadpool.start(worker)
def add_to_textfield(self, s: str): def add_to_textfield(self, s: str):
self.text.appendPlainText(s) self.text.appendPlainText(s)
@@ -289,7 +370,7 @@ class PyRelacs(QMainWindow):
log.info("exit button!") log.info("exit button!")
self.stop_recording() self.stop_recording()
self.add_to_textfield("exiting") self.add_to_textfield("exiting")
if self.config.settings.daq: if self.mccdaq:
self.mccdaq.disconnect_daq() self.mccdaq.disconnect_daq()
log.info("closing GUI") log.info("closing GUI")
self.close() self.close()

View File

@@ -15,6 +15,8 @@ class Continously:
def __init__(self, figure: pg.GraphicsLayoutWidget, buffer: CircBuffer): def __init__(self, figure: pg.GraphicsLayoutWidget, buffer: CircBuffer):
self.figure = figure self.figure = figure
self.buffer = buffer self.buffer = buffer
self.last_plotted_index = 0
self.timer = QTimer()
def plot(self, *args, **kwargs): def plot(self, *args, **kwargs):
self.figure.setBackground("w") self.figure.setBackground("w")
@@ -35,10 +37,8 @@ class Continously:
) )
# self.plot_index = 0 # self.plot_index = 0
self.timer = QTimer()
self.CHUNK_PLOT = int(self.buffer.samplerate / 6) self.CHUNK_PLOT = int(self.buffer.samplerate / 6)
self.PLOT_HISTORY = 500_000 # The amount of data you want to keep on screen self.PLOT_HISTORY = 500_000 # The amount of data you want to keep on screen
self.last_plotted_index = 0
self.timer.setInterval(150) self.timer.setInterval(150)
self.timer.timeout.connect(self.update_plot) self.timer.timeout.connect(self.update_plot)
self.timer.start() self.timer.start()
@@ -49,18 +49,20 @@ class Continously:
start_time = time.time() start_time = time.time()
if total_count - self.last_plotted_index >= self.CHUNK_PLOT: if total_count - self.last_plotted_index >= self.CHUNK_PLOT:
times, items = self.buffer.read( try:
self.last_plotted_index, times, items = self.buffer.read(
extend=self.CHUNK_PLOT, self.last_plotted_index,
) extend=self.CHUNK_PLOT,
)
self.time = np.concatenate((self.time, times))[-self.PLOT_HISTORY :] self.time = np.concatenate((self.time, times))[-self.PLOT_HISTORY :]
self.data = np.concatenate((self.data, items))[-self.PLOT_HISTORY :] self.data = np.concatenate((self.data, items))[-self.PLOT_HISTORY :]
self.line.setData( self.line.setData(
self.time, self.time,
self.data, self.data,
) )
self.last_plotted_index += self.CHUNK_PLOT self.last_plotted_index += self.CHUNK_PLOT
except IndexError:
log.error("Could not acces the data from the buffer for plotting")
end_time = time.time() end_time = time.time()
log.debug(f"total time for plotting {end_time - start_time}") log.debug(f"total time for plotting {end_time - start_time}")
else: else:
@@ -68,6 +70,19 @@ class Continously:
def stop_plotting(self): def stop_plotting(self):
self.timer.stop() self.timer.stop()
if self.last_plotted_index > 0:
total_count = self.buffer.totalcount()
times, items = self.buffer.read(
self.last_plotted_index,
extend=total_count - self.last_plotted_index,
)
self.time = np.concatenate((self.time, times))[-self.PLOT_HISTORY :]
self.data = np.concatenate((self.data, items))[-self.PLOT_HISTORY :]
self.line.setData(
self.time,
self.data,
)
self.last_plotted_index += total_count - self.last_plotted_index
def refresh(self): def refresh(self):
self.continous_ax.enableAutoRange() self.continous_ax.enableAutoRange()