16 Commits

Author SHA1 Message Date
wendtalexander
0113e94625 [dataio/nix] adding comments 2024-11-04 08:04:20 +01:00
wendtalexander
cce7c55fe7 [daq] trying different channels 2024-10-25 18:03:43 +02:00
wendtalexander
6c49f19b43 [dataio/daq] updating log messages 2024-10-25 18:03:23 +02:00
wendtalexander
2ef018ef07 [dataio/daq] making the buffer bigger 2024-10-24 16:35:09 +02:00
wendtalexander
3ab7a33b52 [config] updating config 2024-10-24 11:51:27 +02:00
wendtalexander
acd41302c7 [ui/plots] plotting now two different channels from the buffer 2024-10-24 11:51:17 +02:00
wendtalexander
1fe854b74e [ui] moving creation of nix to nix_file 2024-10-24 11:50:49 +02:00
wendtalexander
a53ff62d96 [dataio/nix] moving creation of nix to nix writer 2024-10-24 11:50:32 +02:00
wendtalexander
3d3d9a0cdd [dataio/daq] writes now two channels in the ringbuffer 2024-10-24 11:50:00 +02:00
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
11 changed files with 426 additions and 154 deletions

View File

@@ -1,9 +1,11 @@
settings:
# If true daq should be used, else starts without daq
daq: False
daq: True
# class names of the repros to run
repros: [Calibration, Sinus]
path: ~/projects/pyrelacs/test/
# string to append after the file name
postappend: ehpys
metadata:
SetupName : Setup1

View File

@@ -21,7 +21,6 @@ class DaqProducer:
self.device = device
self.ai_device = self.device.get_ai_device()
self.channels = channels
self.stop = False
def read_analog_continously(
@@ -41,7 +40,7 @@ class DaqProducer:
)
# let the buffer for the daq device hold 5 seconds of data
daq_buffer_size = int(self.buffer.samplerate * 5)
daq_buffer_size = int(self.buffer.samplerate * 30)
data_in = uldaq.create_float_buffer(channel_range.size, daq_buffer_size)
log.debug(f"Buffersize for daq {len(data_in)}")
@@ -70,7 +69,12 @@ class DaqProducer:
prev_count = 0
prev_index = 0
while not self.stop:
daq_status, transfer_status = self.ai_device.get_scan_status()
try:
daq_status, transfer_status = self.ai_device.get_scan_status()
except uldaq.ul_exception.ULException as e:
log.error("Could not get the scan status")
log.error("Stopping writting")
break
# The index into the data buffer immediately following the last sample transferred.
current_index = transfer_status.current_index
# total samples since start of the scan
@@ -79,7 +83,7 @@ class DaqProducer:
channel_samples = transfer_status.current_scan_count
new_data_count = total_samples - prev_count
# check if counts if new data is bigger than the buffer
# check if new data is bigger than the buffer
# if that happends stop the acquisition
if new_data_count > len(data_in):
self.ai_device.scan_stop()
@@ -92,23 +96,54 @@ class DaqProducer:
if prev_index + chunk_size > len(data_in) - 1:
log.debug("Chunk wraps around buffersize")
first_chunk = len(data_in) - prev_index
data_first_channel = data_in[
prev_index : prev_index + first_chunk : 2
]
data_second_channel = data_in[
prev_index + 1 : prev_index + first_chunk : 2
]
[
self.buffer.append(data_in[prev_index + i])
for i in range(first_chunk)
self.buffer.append(data_first_channel[i], channel=0)
for i in range(int(first_chunk / 2))
]
[
self.buffer.append(data_second_channel[i], channel=1)
for i in range(int(first_chunk / 2))
]
second_chunk = chunk_size - first_chunk
data_first_channel = data_in[0:second_chunk:2]
data_second_channel = data_in[1:second_chunk:2]
[
self.buffer.append(data_in[i])
for i in range(second_chunk)
self.buffer.append(data_first_channel[i], channel=0)
for i in range(int(second_chunk / 2))
]
[
self.buffer.append(data_second_channel[i], channel=1)
for i in range(int(second_chunk / 2))
]
else:
log.debug("Writing chunk to buffer")
# appending to the first channel
data_first_channel = data_in[
prev_index : prev_index + chunk_size : 2
]
data_second_channel = data_in[
prev_index + 1 : prev_index + chunk_size : 2
]
[
self.buffer.append(data_in[prev_index + i])
for i in range(chunk_size)
self.buffer.append(data_first_channel[i], channel=0)
for i in range(int(chunk_size / 2))
]
self.buffer.append(data_in[current_index])
[
self.buffer.append(data_second_channel[i], channel=1)
for i in range(int(chunk_size / 2))
]
if total_samples - prev_count > len(data_in):
self.ai_device.scan_stop()
@@ -124,33 +159,70 @@ class DaqProducer:
self.ai_device.scan_stop()
daq_status, transfer_status = self.ai_device.get_scan_status()
current_index = transfer_status.current_index
log.debug(daq_status)
chunk_size = transfer_status.current_total_count - prev_count
log.debug(transfer_status.current_index)
log.debug(transfer_status.current_total_count)
log.debug(transfer_status.current_scan_count)
log.debug(self.buffer.totalcount())
log.debug(f"DAQ current index {transfer_status.current_index}")
log.debug(f"DAQ total count {transfer_status.current_total_count}")
log.debug(
f"DAQ Samples per channel {transfer_status.current_scan_count}"
)
log.debug("Appending last chunk")
if prev_index + chunk_size > len(data_in) - 1:
log.debug("Chunk wraps around buffersize")
first_chunk = len(data_in) - prev_index
[
self.buffer.append(data_in[prev_index + i])
for i in range(first_chunk)
data_first_channel = data_in[
prev_index : prev_index + first_chunk : 2
]
second_chunk = chunk_size - first_chunk
[self.buffer.append(data_in[i]) for i in range(second_chunk)]
else:
log.debug("Writing chunk to buffer")
[
self.buffer.append(data_in[prev_index + i])
for i in range(chunk_size)
data_second_channel = data_in[
prev_index + 1 : prev_index + first_chunk : 2
]
self.buffer.append(data_in[current_index])
[
self.buffer.append(data_first_channel[i], channel=0)
for i in range(int(first_chunk / 2))
]
[
self.buffer.append(data_second_channel[i], channel=1)
for i in range(int(first_chunk / 2))
]
second_chunk = chunk_size - first_chunk
data_first_channel = data_in[0:second_chunk:2]
data_second_channel = data_in[1:second_chunk:2]
[
self.buffer.append(data_first_channel[i], channel=0)
for i in range(int(second_chunk / 2))
]
[
self.buffer.append(data_second_channel[i], channel=1)
for i in range(int(second_chunk / 2))
]
else:
log.debug("Writing chunk to buffer")
# appending to the first channel
data_first_channel = data_in[
prev_index : prev_index + chunk_size : 2
]
data_second_channel = data_in[
prev_index + 1 : prev_index + chunk_size : 2
]
[
self.buffer.append(data_first_channel[i], channel=0)
for i in range(int(chunk_size / 2))
]
[
self.buffer.append(data_second_channel[i], channel=1)
for i in range(int(chunk_size / 2))
]
log.info("stopping")
log.debug(self.buffer.totalcount())
log.debug(self.ai_device.get_scan_status())
break
break

View File

@@ -1,4 +1,9 @@
from datetime import datetime
import itertools
import string
import time
from dataclasses import asdict
from IPython import embed
from PyQt6.QtCore import QMutex
import nixio
@@ -10,8 +15,9 @@ log = config_logging()
class NixWriter:
def __init__(self, buffer: CircBuffer) -> None:
def __init__(self, buffer: CircBuffer, config) -> None:
self.buffer = buffer
self.config = config
def write_nix(
self,
@@ -62,11 +68,42 @@ class NixWriter:
log.debug(f"Samples written {index}")
def _write_header(self):
"""
Writing the header of the nix file
"""
self.nix_file = nixio.File.open(path="data.nix", mode=nixio.FileMode.Overwrite)
self.block = self.nix_file.create_block("recording", "testfile")
self.data_array = self.block.create_data_array(
"Analog1", "ndarray", shape=(1000,), dtype=nixio.DataType.Double
)
def generate_letter_sequence(self):
alphabet = string.ascii_lowercase
for size in range(2, 3):
for combo in itertools.product(alphabet, repeat=size):
yield "".join(combo)
def create_nix_file(self, file_path, metadata):
data_time = datetime.now().strftime("%Y-%m-%t_%H-%M-%S")
sequence_generator = self.generate_letter_sequence()
sequence = next(sequence_generator)
self.nix_file = nixio.File.open(
path=f"{file_path}/{data_time}_{sequence}.nix",
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
)
return self.data_array_analog1, self.data_array_analog2
def stop_writing(self):
self.write = False

View File

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

View File

@@ -6,6 +6,8 @@ import uldaq
from IPython import embed
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import welch, find_peaks
import pyqtgraph as pg
from pyrelacs.devices.mccdaq import MccDaq
from pyrelacs.util.logging import config_logging
@@ -15,40 +17,50 @@ log = config_logging()
faulthandler.enable()
class Calibration(MccDaq):
def __init__(self) -> None:
super().__init__()
class Calibration:
def __init__(self, config, mccdaq: MccDaq) -> None:
self.config = config
self.mccdaq = mccdaq
self.SAMPLERATE = 40_000.0
self.DURATION = 5
self.AMPLITUDE = 1
self.SINFREQ = 750
@staticmethod
def run(nix_file: nix.File):
calb = Calibration()
calb.check_beat(nix_file)
def run(*args, **kwargs):
nix_block = args[0]
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):
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)
self.mccdaq.set_attenuation_level(db_channel1=0.0, db_channel2=0.0)
# write to ananlog 1
t = np.arange(0, self.DURATION, 1 / self.SAMPLERATE)
data = self.AMPLITUDE * np.sin(2 * np.pi * self.SINFREQ * t)
fig, ax = plt.subplots()
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}")
stim = self.write_analog(
stim = self.mccdaq.write_analog(
data,
[0, 0],
self.SAMPLERATE,
ScanOption=uldaq.ScanOption.EXTTRIGGER,
)
data_channel_one = self.read_analog(
data_channel_one = self.mccdaq.read_analog(
[0, 0],
self.DURATION,
self.SAMPLERATE,
@@ -57,21 +69,21 @@ class Calibration(MccDaq):
time.sleep(1)
log.debug("Starting the Scan")
self.digital_trigger()
self.mccdaq.digital_trigger()
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")
self.write_bit(channel=0, bit=0)
self.mccdaq.write_bit(channel=0, bit=0)
time.sleep(1)
self.set_analog_to_zero()
self.mccdaq.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)
self.mccdaq.write_bit(channel=0, bit=0)
time.sleep(1)
self.set_analog_to_zero()
self.disconnect_daq()
self.mccdaq.set_analog_to_zero()
# self.mccdaq.disconnect_daq()
if i == 0:
ax.plot(t, stim, label=f"Input_{db_value}", color=colors[i])
@@ -80,34 +92,33 @@ class Calibration(MccDaq):
ax.legend()
plt.show()
self.disconnect_daq()
# self.mccdaq.disconnect_daq()
def check_beat(self, nix_file: nix.File):
self.set_attenuation_level(db_channel1=-10.0, db_channel2=0.0)
def check_beat(self, nix_block: nix.Block):
self.mccdaq.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"]
block = nix_file.create_block("Calibration", "data")
# 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(
self.mccdaq.set_attenuation_level(db_channel1=db_value)
stim = self.mccdaq.write_analog(
data,
[0, 0],
self.SAMPLERATE,
ScanOption=uldaq.ScanOption.EXTTRIGGER,
)
readout = self.read_analog(
readout = self.mccdaq.read_analog(
[0, 1],
self.DURATION,
self.SAMPLERATE,
ScanOption=uldaq.ScanOption.EXTTRIGGER,
)
self.digital_trigger()
log.info(self.ao_device)
self.mccdaq.digital_trigger()
log.info(self.mccdaq.ao_device)
ai_status = uldaq.ScanStatus.RUNNING
ao_status = uldaq.ScanStatus.RUNNING
@@ -119,10 +130,10 @@ class Calibration(MccDaq):
):
# log.debug("Scanning")
time.time_ns()
ai_status = self.ai_device.get_scan_status()[0]
ao_status = self.ao_device.get_scan_status()[0]
ai_status = self.mccdaq.ai_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(
f"Status Analog_output {ao_status}\n, Status Analog_input {ai_status}"
)
@@ -130,7 +141,7 @@ class Calibration(MccDaq):
channel1 = np.array(readout[::2])
channel2 = np.array(readout[1::2])
stim_data = block.create_data_array(
stim_data = nix_block.create_data_array(
f"stimulus_{db_value}",
"nix.regular_sampled",
shape=data.shape,
@@ -143,7 +154,7 @@ class Calibration(MccDaq):
label="time",
unit="s",
)
fish_data = block.create_data_array(
fish_data = nix_block.create_data_array(
f"fish_{db_value}",
"Array",
shape=data.shape,
@@ -157,7 +168,72 @@ class Calibration(MccDaq):
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):

View File

View File

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

@@ -7,6 +7,8 @@ from PyQt6.QtGui import QAction, QIcon, QKeySequence
from PyQt6.QtCore import Qt, QSize, QThreadPool, QMutex
from PyQt6.QtWidgets import (
QGridLayout,
QPushButton,
QTabWidget,
QToolBar,
QWidget,
QMainWindow,
@@ -47,11 +49,15 @@ class PyRelacs(QMainWindow):
super().__init__()
# loaded config
self.config = config
# check if daq is connencted else None
if self.config.settings.daq:
start = time.time()
self.mccdaq = MccDaq()
end = time.time()
log.debug(f"Connection to DAQ took {end - start}")
else:
self.mccdaq = None
self.repros = Repro()
@@ -69,19 +75,6 @@ class PyRelacs(QMainWindow):
self.text = QPlainTextEdit()
self.text.setReadOnly(True)
self.setMenuBar(QMenuBar(self))
self.setStatusBar(QStatusBar(self))
self.create_actions()
self.create_toolbars()
layout = QGridLayout()
layout.addWidget(self.figure, 0, 0, 2, 2)
layout.addWidget(self.text, 2, 0, 1, 2)
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
SAMPLERATE = pq.Quantity(
self.config.pyrelacs.data.input.inputsamplerate,
self.config.pyrelacs.data.input.inputsamplerateunit,
@@ -99,19 +92,34 @@ class PyRelacs(QMainWindow):
self.buffer = CircBuffer(
size=int(BUFFERSIZE.base),
samplerate=float(SAMPLERATE.base),
channels=2,
mutex=self.mutex,
)
self.continously_plot = Continously(self.figure, self.buffer)
# self.continously_plot.plot()
if self.config.settings.daq:
if self.mccdaq:
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, [4, 5])
log.debug("Creating Sinus Generator")
self.sinus_producer = SinProducer(self.buffer)
self.nix_writer = NixWriter(self.buffer)
self.create_nix_file(f"{_root}/test.nix", self.config.metadata)
self.nix_writer = NixWriter(self.buffer, self.config)
self.setMenuBar(QMenuBar(self))
self.setStatusBar(QStatusBar(self))
self.create_actions()
self.create_toolbars()
self.repro_tabs = QTabWidget()
self.create_repros_tabs()
layout = QGridLayout()
layout.addWidget(self.figure, 0, 0, 2, 2)
layout.addWidget(self.repro_tabs, 2, 0, 2, 2)
layout.addWidget(self.text, 4, 0, 1, 1)
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
def create_actions(self):
self._rlx_exitaction = QAction(QIcon(":/icons/exit.png"), "Exit", self)
@@ -127,7 +135,7 @@ class PyRelacs(QMainWindow):
self._daq_connectaction = QAction(
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.setShortcut(QKeySequence("Alt+d"))
self._daq_connectaction.triggered.connect(self.mccdaq.connect_dac)
@@ -146,7 +154,7 @@ class PyRelacs(QMainWindow):
# # self._daq_calibaction.setShortcut(QKeySequence("Alt+d"))
# 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_sinus_action = QAction(QIcon(":/icons/record.png"), "Sinus", self)
@@ -211,34 +219,53 @@ class PyRelacs(QMainWindow):
daq_toolbar.addAction(self._record)
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(
include_repros=self.config.settings.repros
)
figures_repros = {rep: pg.GraphicsLayoutWidget() for rep in repro_names}
for rep, fn in zip(repro_names, file_names):
repro_action = QAction(rep, self)
repro_action.setStatusTip(rep)
repro_action.triggered.connect(
lambda checked, n=rep, f=fn: self.run_repro(n, f)
tab = QWidget()
tab_layout = QGridLayout()
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,
figures_repros,
self.mccdaq,
self.config,
)
)
repro_toolbar.addAction(repro_action)
self.addToolBar(Qt.ToolBarArea.BottomToolBarArea, repro_toolbar)
tab_layout.addWidget(run_repro_button, 0, 0, 1, 0)
tab_layout.addWidget(figures_repros[rep], 1, 0, 1, 1)
tab.setLayout(tab_layout)
self.repro_tabs.addTab(tab, f"{rep}")
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
def run_repro(
self,
name_of_repro: str,
file_of_repro: str,
figures,
*args,
):
self.text.appendPlainText(f"started Repro {name_of_repro}, {file_of_repro}")
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
figure_repro = figures[name_of_repro]
worker = Worker(
self.repros.run_repro,
name_of_repro,
file_of_repro,
figure_repro,
*args[-1:],
)
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 recenter_continously_plot(self):
self.continously_plot.refresh()
@@ -269,7 +296,9 @@ class PyRelacs(QMainWindow):
self.continously_plot.plot()
def record(self):
self.create_nix_file("test.nix", self.config.metadata)
self.data_array_analog1, self.data_array_analog2 = (
self.nix_writer.create_nix_file(f"{_root}/test/", self.config.metadata)
)
log.debug("Created nix file")
nix_writer = Worker(
@@ -308,20 +337,9 @@ class PyRelacs(QMainWindow):
except AttributeError:
log.debug("Did not generate Sinus")
if hasattr(PyRelacs, "daq_device"):
if self.config.settings.daq:
log.debug("Stopping DAQ")
self.daq_producer.stop_aquisition()
embed()
exit()
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):
self.text.appendPlainText(s)
@@ -330,7 +348,7 @@ class PyRelacs(QMainWindow):
log.info("exit button!")
self.stop_recording()
self.add_to_textfield("exiting")
if self.config.settings.daq:
if self.mccdaq:
self.mccdaq.disconnect_daq()
log.info("closing GUI")
self.close()

View File

@@ -15,7 +15,9 @@ class Continously:
def __init__(self, figure: pg.GraphicsLayoutWidget, buffer: CircBuffer):
self.figure = figure
self.buffer = buffer
self.last_plotted_index = 0
self.last_plotted_index_analog_in_0 = 0
self.last_plotted_index_analog_in_1 = 0
self.timer = QTimer()
def plot(self, *args, **kwargs):
self.figure.setBackground("w")
@@ -23,44 +25,89 @@ class Continously:
prev_plot = self.figure.getItem(row=0, col=0)
if prev_plot:
self.figure.removeItem(prev_plot)
self.continous_ax = self.figure.addPlot(row=0, col=0)
self.analog_in_0 = self.figure.addPlot(row=0, col=0)
self.analog_in_1 = self.figure.addPlot(row=1, col=0)
pen = pg.mkPen("red")
self.time = np.zeros(self.buffer.size)
self.data = np.empty(self.buffer.size)
self.line = self.continous_ax.plot(
self.time,
self.data,
self.time_analog_in_0 = np.zeros(self.buffer.size)
self.data_analog_in_0 = np.empty(self.buffer.size)
self.line_analog_in_0 = self.analog_in_0.plot(
self.time_analog_in_0,
self.data_analog_in_0,
pen=pen,
# symbol="o",
)
pen = pg.mkPen("red")
self.time_analog_in_1 = np.zeros(self.buffer.size)
self.data_analog_in_1 = np.empty(self.buffer.size)
self.line_analog_in_1 = self.analog_in_1.plot(
self.time_analog_in_1,
self.data_analog_in_1,
pen=pen,
# symbol="o",
)
# self.plot_index = 0
self.timer = QTimer()
self.CHUNK_PLOT = int(self.buffer.samplerate / 6)
self.PLOT_HISTORY = 500_000 # The amount of data you want to keep on screen
self.timer.setInterval(150)
self.timer.timeout.connect(self.update_plot)
self.timer.timeout.connect(self.update_plot_1)
self.timer.start()
def update_plot(self):
current_index = self.buffer.write_index()
total_count = self.buffer.totalcount()
total_count = self.buffer.totalcount(channel=0)
start_time = time.time()
if total_count - self.last_plotted_index >= self.CHUNK_PLOT:
if total_count - self.last_plotted_index_analog_in_0 >= self.CHUNK_PLOT:
try:
times, items = self.buffer.read(
self.last_plotted_index,
self.last_plotted_index_analog_in_0,
extend=self.CHUNK_PLOT,
channel=0,
)
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.time_analog_in_0 = np.concatenate((self.time_analog_in_0, times))[
-self.PLOT_HISTORY :
]
self.data_analog_in_0 = np.concatenate((self.data_analog_in_0, items))[
-self.PLOT_HISTORY :
]
self.line_analog_in_0.setData(
self.time_analog_in_0,
self.data_analog_in_0,
)
self.last_plotted_index += self.CHUNK_PLOT
self.last_plotted_index_analog_in_0 += self.CHUNK_PLOT
except IndexError:
log.error("Could not acces the data from the buffer for plotting")
end_time = time.time()
log.debug(f"total time for plotting {end_time - start_time}")
else:
pass
def update_plot_1(self):
total_count = self.buffer.totalcount(channel=1)
start_time = time.time()
if total_count - self.last_plotted_index_analog_in_1 >= self.CHUNK_PLOT:
try:
times, items = self.buffer.read(
self.last_plotted_index_analog_in_1,
extend=self.CHUNK_PLOT,
channel=1,
)
self.time_analog_in_1 = np.concatenate((self.time_analog_in_0, times))[
-self.PLOT_HISTORY :
]
self.data_analog_in_1 = np.concatenate((self.data_analog_in_0, items))[
-self.PLOT_HISTORY :
]
self.line_analog_in_1.setData(
self.time_analog_in_1,
self.data_analog_in_1,
)
self.last_plotted_index_analog_in_1 += self.CHUNK_PLOT
except IndexError:
log.error("Could not acces the data from the buffer for plotting")
end_time = time.time()
@@ -70,18 +117,26 @@ class Continously:
def stop_plotting(self):
self.timer.stop()
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
if self.last_plotted_index_analog_in_0 > 0:
total_count = self.buffer.totalcount()
times, items = self.buffer.read(
self.last_plotted_index_analog_in_0,
extend=total_count - self.last_plotted_index_analog_in_0,
)
self.time_analog_in_0 = np.concatenate((self.time_analog_in_0, times))[
-self.PLOT_HISTORY :
]
self.data_analog_in_0 = np.concatenate((self.data_analog_in_0, items))[
-self.PLOT_HISTORY :
]
self.line_analog_in_0.setData(
self.time_analog_in_0,
self.data_analog_in_0,
)
self.last_plotted_index_analog_in_0 += (
total_count - self.last_plotted_index_analog_in_0
)
def refresh(self):
self.continous_ax.enableAutoRange()
self.analog_in_0.enableAutoRange()
self.analog_in_1.enableAutoRange()