Compare commits
12 Commits
afc37adb1a
...
4029034174
Author | SHA1 | Date | |
---|---|---|---|
4029034174 | |||
9fd4892325 | |||
85b5a71ccb | |||
5d62cb0384 | |||
64cd1b00ad | |||
f703687ed7 | |||
4e0a1f0ac5 | |||
4864538213 | |||
28dd0b7080 | |||
b94078634d | |||
e3c867f4fd | |||
13897f29e3 |
@ -1,5 +1,8 @@
|
||||
settings:
|
||||
repros: [calibration, sinus]
|
||||
# If true daq should be used, else starts without daq
|
||||
daq: False
|
||||
# class names of the repros to run
|
||||
repros: [Calibration, Sinus]
|
||||
path: ~/projects/pyrelacs/test/
|
||||
|
||||
metadata:
|
||||
@ -16,9 +19,11 @@ pyrelacs:
|
||||
data:
|
||||
input:
|
||||
inputsamplerate : 20
|
||||
# Unit is rescaled to Hz
|
||||
inputsamplerateunit : kHz
|
||||
# BufferSize
|
||||
inputtracecapacity : 600
|
||||
# Unit is rescaled to s
|
||||
inputtracecapacityunit : s
|
||||
inputunipolar : false
|
||||
inputtraceid : [ V-1, EOD, LocalEOD-1, GlobalEFieldStimulus ]
|
||||
@ -56,8 +61,8 @@ pyrelacs:
|
||||
|
||||
devices:
|
||||
DAQFlexCore:
|
||||
analogoutputpins : [0,1]
|
||||
analoginputpinshigh : [0,1,2,3,4,5,6,7]
|
||||
analogoutputpins : [0, 1]
|
||||
analoginputpinshigh : [0, 1, 2, 3,4,5,6,7]
|
||||
analoginputpinslow : [1,2]
|
||||
digitalpins : [0,1,2,3]
|
||||
|
||||
|
@ -21,6 +21,7 @@ class ValueUnit:
|
||||
|
||||
@dataclass
|
||||
class Settings:
|
||||
daq: bool
|
||||
repros: list[str]
|
||||
path: str
|
||||
|
||||
|
@ -9,7 +9,7 @@ class CircBuffer:
|
||||
self,
|
||||
size: int,
|
||||
channels: int = 1,
|
||||
samplerate: int = 40_000,
|
||||
samplerate: float = 40_000.0,
|
||||
mutex: QMutex = QMutex(),
|
||||
):
|
||||
self.__size = size
|
||||
|
@ -41,7 +41,7 @@ class DaqProducer:
|
||||
)
|
||||
|
||||
# let the buffer for the daq device hold 5 seconds of data
|
||||
daq_buffer_size = self.buffer.samplerate * 5
|
||||
daq_buffer_size = int(self.buffer.samplerate * 5)
|
||||
|
||||
data_in = uldaq.create_float_buffer(channel_range.size, daq_buffer_size)
|
||||
log.debug(f"Buffersize for daq {len(data_in)}")
|
||||
|
@ -18,12 +18,12 @@ class NixWriter:
|
||||
log.debug("Starting the writing")
|
||||
self.write = True
|
||||
while self.write:
|
||||
log.debug(items)
|
||||
# log.debug(items)
|
||||
try:
|
||||
data, _ = self.buffer.read(items, extend=chunk)
|
||||
self.data_array.append(data)
|
||||
except IndexError as e:
|
||||
log.debug(f"{e}")
|
||||
# log.debug(f"{e}")
|
||||
continue
|
||||
items += chunk
|
||||
log.debug("Stoppint the writing")
|
||||
|
@ -8,7 +8,6 @@ from pyrelacs.util.logging import config_logging
|
||||
log = config_logging()
|
||||
|
||||
|
||||
# stopbutton: QAction
|
||||
class SinProducer:
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -41,13 +41,16 @@ class MccDaq:
|
||||
try:
|
||||
self.daq_device.connect()
|
||||
except uldaq.ul_exception.ULException:
|
||||
self.disconnect_dac()
|
||||
self.disconnect_daq()
|
||||
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()
|
||||
log.debug("Connected")
|
||||
|
||||
log.debug("Connected to MccDaq")
|
||||
log.debug("Activating the Attenuator")
|
||||
self.activate_attenuator()
|
||||
|
||||
def connect_dac(self):
|
||||
"""
|
||||
@ -194,7 +197,7 @@ class MccDaq:
|
||||
except Exception as e:
|
||||
print(f"{e}")
|
||||
self.set_analog_to_zero()
|
||||
self.disconnect_dac()
|
||||
self.disconnect_daq()
|
||||
|
||||
return data_analog_output
|
||||
|
||||
@ -224,7 +227,7 @@ class MccDaq:
|
||||
except Exception as e:
|
||||
log.error("f{e}")
|
||||
log.error("disconnection dac")
|
||||
self.disconnect_dac()
|
||||
self.disconnect_daq()
|
||||
|
||||
def digital_trigger(self, ch: int = 0) -> None:
|
||||
"""
|
||||
@ -281,7 +284,9 @@ class MccDaq:
|
||||
bit = self.dio_device.d_bit_in(uldaq.DigitalPortType.AUXPORT, channel)
|
||||
return bit
|
||||
|
||||
def disconnect_dac(self):
|
||||
def disconnect_daq(self):
|
||||
log.debug("Disconnecting DAQ")
|
||||
self.deactivate_attenuator()
|
||||
self.daq_device.disconnect()
|
||||
self.daq_device.release()
|
||||
|
||||
@ -329,12 +334,12 @@ class MccDaq:
|
||||
except uldaq.ul_exception.ULException:
|
||||
log.debug("Operation timed out")
|
||||
self.write_bit(channel=0, bit=0)
|
||||
self.disconnect_dac()
|
||||
self.disconnect_daq()
|
||||
self.connect_dac()
|
||||
self.set_analog_to_zero()
|
||||
finally:
|
||||
self.write_bit(channel=0, bit=0)
|
||||
self.disconnect_dac()
|
||||
self.disconnect_daq()
|
||||
self.connect_dac()
|
||||
self.set_analog_to_zero()
|
||||
|
||||
|
@ -71,7 +71,7 @@ class Calibration(MccDaq):
|
||||
self.write_bit(channel=0, bit=0)
|
||||
time.sleep(1)
|
||||
self.set_analog_to_zero()
|
||||
self.disconnect_dac()
|
||||
self.disconnect_daq()
|
||||
|
||||
if i == 0:
|
||||
ax.plot(t, stim, label=f"Input_{db_value}", color=colors[i])
|
||||
@ -80,7 +80,7 @@ class Calibration(MccDaq):
|
||||
ax.legend()
|
||||
plt.show()
|
||||
|
||||
self.disconnect_dac()
|
||||
self.disconnect_daq()
|
||||
|
||||
def check_beat(self, nix_file: nix.File):
|
||||
self.set_attenuation_level(db_channel1=-10.0, db_channel2=0.0)
|
@ -44,10 +44,15 @@ class Repro:
|
||||
else:
|
||||
raise AttributeError(f"{file.name} has no {name} class")
|
||||
|
||||
def names_of_repros(self) -> Tuple[list, list]:
|
||||
def names_of_repros(self, include_repros: list[str]) -> Tuple[list, list]:
|
||||
"""
|
||||
Searches for class names in the repro folder in all python files
|
||||
|
||||
Parameters
|
||||
----------
|
||||
include_repros : list[str]
|
||||
List of repros to include in the pyrelacs instance
|
||||
|
||||
Returns
|
||||
-------
|
||||
Tuple[list, list]
|
||||
@ -73,4 +78,7 @@ class Repro:
|
||||
repro_names.extend(class_name)
|
||||
file_names.append(python_file)
|
||||
file.close()
|
||||
|
||||
repro_names = [r for r in repro_names if r in include_repros]
|
||||
file_names = [f for r, f in zip(repro_names, file_names) if r in include_repros]
|
||||
return repro_names, file_names
|
||||
|
3
pyrelacs/repros/sinus.py
Normal file
3
pyrelacs/repros/sinus.py
Normal file
@ -0,0 +1,3 @@
|
||||
class Sinus:
|
||||
def __init__(self) -> None:
|
||||
pass
|
@ -2,7 +2,7 @@ import time
|
||||
from pathlib import Path as path
|
||||
|
||||
from PyQt6.QtGui import QAction, QIcon, QKeySequence
|
||||
from PyQt6.QtCore import Qt, QSize, QThreadPool, QMutex, QTimer
|
||||
from PyQt6.QtCore import Qt, QSize, QThreadPool, QMutex
|
||||
from PyQt6.QtWidgets import (
|
||||
QGridLayout,
|
||||
QToolBar,
|
||||
@ -16,16 +16,17 @@ from PyQt6.QtWidgets import (
|
||||
import uldaq
|
||||
import nixio as nix
|
||||
import pyqtgraph as pg
|
||||
import numpy as np
|
||||
import quantities as pq
|
||||
|
||||
from pyrelacs.devices.mccdaq import MccDaq
|
||||
|
||||
from pyrelacs.dataio.circbuffer import CircBuffer
|
||||
from pyrelacs.dataio.daq_producer import DaqProducer
|
||||
from pyrelacs.dataio.nix_writer import NixWriter
|
||||
from pyrelacs.dataio.sin_producer import SinProducer
|
||||
|
||||
from pyrelacs.worker import Worker
|
||||
from pyrelacs.repros.repros import Repro
|
||||
from pyrelacs.dataio.circbuffer import CircBuffer
|
||||
|
||||
from pyrelacs.ui.about import AboutDialog
|
||||
from pyrelacs.ui.plots.calibration import CalibrationPlot
|
||||
@ -42,28 +43,26 @@ from IPython import embed
|
||||
class PyRelacs(QMainWindow):
|
||||
def __init__(self, config):
|
||||
super().__init__()
|
||||
# loaded config
|
||||
self.config = config
|
||||
if self.config.settings.daq:
|
||||
start = time.time()
|
||||
self.mccdaq = MccDaq()
|
||||
end = time.time()
|
||||
log.debug(f"Connection to DAQ took {end - start}")
|
||||
|
||||
self.repros = Repro()
|
||||
|
||||
self.setToolButtonStyle(
|
||||
Qt.ToolButtonStyle.ToolButtonTextBesideIcon
|
||||
) # Ensure icons are displayed with text
|
||||
self.setWindowTitle("PyRelacs")
|
||||
|
||||
self.mutex = QMutex()
|
||||
self.timer = QTimer(self)
|
||||
self.timer.setInterval(200)
|
||||
|
||||
self.figure = pg.GraphicsLayoutWidget()
|
||||
|
||||
# filename = path.joinpath(path.cwd(), "data.nix")
|
||||
# if filename.exists():
|
||||
# self.nix_file = nix.File.open(str(filename), nix.FileMode.ReadOnly)
|
||||
# filename = path.joinpath(path.cwd(), "calibration.nix")
|
||||
# self.nix_file = nix.File.open(str(filename), nix.FileMode.Overwrite)
|
||||
#
|
||||
# self.calibration_plot = CalibrationPlot(self.figure, self.nix_file)
|
||||
# self.nix_file.close()
|
||||
|
||||
self.threadpool = QThreadPool()
|
||||
self.repros = Repro()
|
||||
|
||||
self.text = QPlainTextEdit()
|
||||
self.text.setReadOnly(True)
|
||||
@ -84,33 +83,31 @@ class PyRelacs(QMainWindow):
|
||||
SAMPLERATE = pq.Quantity(
|
||||
self.config.pyrelacs.data.input.inputsamplerate,
|
||||
self.config.pyrelacs.data.input.inputsamplerateunit,
|
||||
)
|
||||
).rescale("Hz")
|
||||
|
||||
INPUTTRACECAPACITY = pq.Quantity(
|
||||
self.config.pyrelacs.data.input.inputtracecapacity,
|
||||
self.config.pyrelacs.data.input.inputtracecapacityunit,
|
||||
)
|
||||
).rescale("s")
|
||||
start = time.time()
|
||||
BUFFERSIZE = (SAMPLERATE * INPUTTRACECAPACITY).simplified
|
||||
end = time.time()
|
||||
log.debug(f"Buffer allocation took {end - start}")
|
||||
|
||||
self.buffer = CircBuffer(
|
||||
size=BUFFERSIZE, samplerate=SAMPLERATE, mutex=self.mutex
|
||||
size=int(BUFFERSIZE.base),
|
||||
samplerate=float(SAMPLERATE.base),
|
||||
mutex=self.mutex,
|
||||
)
|
||||
self.continously_plot = Continously(self.figure, self.buffer)
|
||||
self.continously_plot.plot()
|
||||
|
||||
start = time.time()
|
||||
self.connect_dac()
|
||||
end = time.time()
|
||||
log.debug(f"Connection to DAQ took {end - start}")
|
||||
|
||||
if hasattr(PyRelacs, "daq_device"):
|
||||
if self.config.settings.daq:
|
||||
log.debug("Creating Daq Generator")
|
||||
self.daq_producer = DaqProducer(self.buffer, self.daq_device, [1, 1])
|
||||
else:
|
||||
log.debug("Creating Sinus Generator")
|
||||
self.sinus_producer = SinProducer(self.buffer)
|
||||
self.daq_producer = DaqProducer(self.buffer, self.mccdaq.daq_device, [1, 1])
|
||||
|
||||
log.debug("Creating Sinus Generator")
|
||||
self.sinus_producer = SinProducer(self.buffer)
|
||||
|
||||
self.nix_writer = NixWriter(self.buffer)
|
||||
|
||||
@ -128,16 +125,17 @@ class PyRelacs(QMainWindow):
|
||||
self._daq_connectaction = QAction(
|
||||
QIcon(":icons/connect.png"), "Connect DAQ", self
|
||||
)
|
||||
self._daq_connectaction.setStatusTip("Connect to daq device")
|
||||
# self._daq_connectaction.setShortcut(QKeySequence("Alt+d"))
|
||||
self._daq_connectaction.triggered.connect(self.connect_dac)
|
||||
if self.config.settings.daq:
|
||||
self._daq_connectaction.setStatusTip("Connect to daq device")
|
||||
# self._daq_connectaction.setShortcut(QKeySequence("Alt+d"))
|
||||
self._daq_connectaction.triggered.connect(self.mccdaq.connect_dac)
|
||||
|
||||
self._daq_disconnectaction = QAction(
|
||||
QIcon(":/icons/disconnect.png"), "Disconnect DAQ", self
|
||||
)
|
||||
self._daq_disconnectaction.setStatusTip("Disconnect the DAQ device")
|
||||
# self._daq_connectaction.setShortcut(QKeySequence("Alt+d"))
|
||||
self._daq_disconnectaction.triggered.connect(self.disconnect_dac)
|
||||
self._daq_disconnectaction = QAction(
|
||||
QIcon(":/icons/disconnect.png"), "Disconnect DAQ", self
|
||||
)
|
||||
self._daq_disconnectaction.setStatusTip("Disconnect the DAQ device")
|
||||
# self._daq_connectaction.setShortcut(QKeySequence("Alt+d"))
|
||||
self._daq_disconnectaction.triggered.connect(self.mccdaq.disconnect_daq)
|
||||
|
||||
# self._daq_calibaction = QAction(
|
||||
# QIcon(":/icons/calibration.png"), "Plot calibration", self
|
||||
@ -176,8 +174,9 @@ class PyRelacs(QMainWindow):
|
||||
file_menu.addAction(self._rlx_aboutaction)
|
||||
|
||||
if device_menu is not None:
|
||||
device_menu.addAction(self._daq_connectaction)
|
||||
device_menu.addAction(self._daq_disconnectaction)
|
||||
if self.config.settings.daq:
|
||||
device_menu.addAction(self._daq_connectaction)
|
||||
device_menu.addAction(self._daq_disconnectaction)
|
||||
device_menu.addSeparator()
|
||||
# device_menu.addAction(self._daq_calibaction)
|
||||
device_menu.addAction(self._run_action)
|
||||
@ -198,8 +197,9 @@ class PyRelacs(QMainWindow):
|
||||
|
||||
self.addToolBar(Qt.ToolBarArea.TopToolBarArea, rlx_toolbar)
|
||||
daq_toolbar = QToolBar("DAQ")
|
||||
daq_toolbar.addAction(self._daq_connectaction)
|
||||
daq_toolbar.addAction(self._daq_disconnectaction)
|
||||
if self.config.settings.daq:
|
||||
daq_toolbar.addAction(self._daq_connectaction)
|
||||
daq_toolbar.addAction(self._daq_disconnectaction)
|
||||
# daq_toolbar.addAction(self._daq_calibaction)
|
||||
daq_toolbar.addAction(self._run_action)
|
||||
daq_toolbar.addAction(self._run_sinus_action)
|
||||
@ -210,7 +210,9 @@ class PyRelacs(QMainWindow):
|
||||
self.addToolBar(Qt.ToolBarArea.TopToolBarArea, daq_toolbar)
|
||||
|
||||
repro_toolbar = QToolBar("Repros")
|
||||
repro_names, file_names = self.repros.names_of_repros()
|
||||
repro_names, file_names = self.repros.names_of_repros(
|
||||
include_repros=self.config.settings.repros
|
||||
)
|
||||
for rep, fn in zip(repro_names, file_names):
|
||||
repro_action = QAction(rep, self)
|
||||
repro_action.setStatusTip(rep)
|
||||
@ -271,24 +273,6 @@ class PyRelacs(QMainWindow):
|
||||
log.debug("Stopping DAQ")
|
||||
self.daq_producer.stop_aquisition()
|
||||
|
||||
def connect_dac(self):
|
||||
devices = uldaq.get_daq_device_inventory(uldaq.InterfaceType.USB)
|
||||
try:
|
||||
self.daq_device = uldaq.DaqDevice(devices[0])
|
||||
log.debug(f"Found daq devices {len(devices)}, connecting to the first one")
|
||||
self.daq_device.connect()
|
||||
log.debug("connected")
|
||||
except IndexError:
|
||||
log.info("DAQ is not connected")
|
||||
log.info("Please connect a DAQ device to the system")
|
||||
|
||||
def disconnect_dac(self):
|
||||
try:
|
||||
self.daq_device.disconnect()
|
||||
self.daq_device.release()
|
||||
except AttributeError:
|
||||
log.debug("DAQ was not connected")
|
||||
|
||||
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)
|
||||
@ -305,7 +289,8 @@ class PyRelacs(QMainWindow):
|
||||
log.info("exit button!")
|
||||
self.stop_recording()
|
||||
self.add_to_textfield("exiting")
|
||||
self.disconnect_dac()
|
||||
if self.config.settings.daq:
|
||||
self.mccdaq.disconnect_daq()
|
||||
log.info("closing GUI")
|
||||
self.close()
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
import time
|
||||
|
||||
import pyqtgraph as pg
|
||||
from IPython import embed
|
||||
import numpy as np
|
||||
@ -24,7 +26,7 @@ class Continously:
|
||||
|
||||
pen = pg.mkPen("red")
|
||||
self.time = np.zeros(self.buffer.size)
|
||||
self.data = np.zeros(self.buffer.size)
|
||||
self.data = np.empty(self.buffer.size)
|
||||
self.line = self.continous_ax.plot(
|
||||
self.time,
|
||||
self.data,
|
||||
@ -34,37 +36,32 @@ class Continously:
|
||||
|
||||
# self.plot_index = 0
|
||||
self.timer = QTimer()
|
||||
self.CHUNK_PLOT = 10_000
|
||||
self.timer.setInterval(200)
|
||||
self.CHUNK_PLOT = 500
|
||||
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.timeout.connect(self.update_plot)
|
||||
self.timer.start()
|
||||
|
||||
def update_plot(self):
|
||||
# log.debug(self.buffer.totalcount())
|
||||
if self.buffer.totalcount() > self.CHUNK_PLOT:
|
||||
log.debug(self.buffer.totalcount())
|
||||
try:
|
||||
times, items = self.buffer.read(
|
||||
self.buffer.write_index() - self.CHUNK_PLOT - 1_000,
|
||||
extend=self.CHUNK_PLOT,
|
||||
)
|
||||
except IndexError as e:
|
||||
items = np.zeros(self.CHUNK_PLOT)
|
||||
times = np.zeros(self.CHUNK_PLOT)
|
||||
log.debug("No Data Available")
|
||||
log.debug(f"Index Error {e}")
|
||||
|
||||
# self.time = np.roll(self.time, -len(items))
|
||||
# self.data = np.roll(self.data, -len(items))
|
||||
#
|
||||
# self.time[-len(times) :] = times
|
||||
# self.data[-len(items) :] = items
|
||||
current_index = self.buffer.write_index()
|
||||
total_count = self.buffer.totalcount()
|
||||
|
||||
start_time = time.time()
|
||||
if total_count - self.last_plotted_index >= self.CHUNK_PLOT:
|
||||
times, items = self.buffer.read(
|
||||
self.last_plotted_index,
|
||||
extend=self.CHUNK_PLOT,
|
||||
)
|
||||
self.time = np.concatenate((self.time, times))[-self.PLOT_HISTORY :]
|
||||
self.data = np.concatenate((self.data, items))[-self.PLOT_HISTORY :]
|
||||
self.line.setData(
|
||||
times,
|
||||
items,
|
||||
self.time,
|
||||
self.data,
|
||||
)
|
||||
# self.plot_index += len(items)
|
||||
self.last_plotted_index += self.CHUNK_PLOT
|
||||
end_time = time.time()
|
||||
log.debug(f"total time for plotting {end_time - start_time}")
|
||||
else:
|
||||
pass
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user