Commit 27508254 authored by Dominique Piche's avatar Dominique Piche

add Haydee's daq gui

parent fd3a8fb1
......@@ -137,15 +137,12 @@ class MecaRobotForDosimetry(MecaRobot):
if self.scintillators_signal_queue is not None:
self.scintillators_signal_file.close()
def deactivate(self):
super().deactivate()
def get_scintillators_signal(self) -> np.ndarray:
"""
Reads the scintillators signal from the signal queue.
"""
time.sleep(0.1)
scintillators_signal = self.signal_queue.get()
scintillators_signal = self.scintillators_signal_queue.get()
return scintillators_signal
def get_scintillators_positions(self) -> np.ndarray:
......
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'daq_acquisition_QtDesigner_gui.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_DAQMainWin(object):
def setupUi(self, DAQMainWin):
DAQMainWin.setObjectName("DAQMainWin")
DAQMainWin.resize(2500, 1450)
self.centralwidget = QtWidgets.QWidget(DAQMainWin)
self.centralwidget.setObjectName("centralwidget")
self.StartDAQAcquisition = QtWidgets.QPushButton(self.centralwidget)
self.StartDAQAcquisition.setGeometry(QtCore.QRect(1110, 20, 161, 41))
self.StartDAQAcquisition.setObjectName("StartDAQAcquisition")
self.StopDAQAcquisition = QtWidgets.QPushButton(self.centralwidget)
self.StopDAQAcquisition.setGeometry(QtCore.QRect(1300, 20, 161, 41))
self.StopDAQAcquisition.setObjectName("StopDAQAcquisition")
self.label_1 = QtWidgets.QLabel(self.centralwidget)
# self.label_1.setGeometry(QtCore.QRect(950, 1080, 250, 40))
self.label_1.setGeometry(QtCore.QRect(1230, 1330, 250, 40))
self.label_1.setObjectName("label_1")
self.label_1.setFont(QtGui.QFont('SansSerif', 10, QtGui.QFont.Bold))
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(120, 55, 250, 40))
self.label_2.setObjectName("label_2")
self.label_2.setFont(QtGui.QFont('SansSerif', 10, QtGui.QFont.Bold))
self.grPlot = PlotWidget(self.centralwidget)
self.grPlot.setGeometry(QtCore.QRect(120, 100, 1150, 600))
self.grPlot.setObjectName("grPlot")
self.grPlot_2 = PlotWidget(self.centralwidget)
self.grPlot_2.setGeometry(QtCore.QRect(1300, 100, 1150, 600))
self.grPlot_2.setObjectName("grPlot_2")
self.grPlot_3 = PlotWidget(self.centralwidget)
self.grPlot_3.setGeometry(QtCore.QRect(120, 710, 1150, 600))
self.grPlot_3.setObjectName("grPlot_3")
self.grPlot_4 = PlotWidget(self.centralwidget)
self.grPlot_4.setGeometry(QtCore.QRect(1300, 710, 1150, 600))
self.grPlot_4.setObjectName("grPlot_4")
DAQMainWin.setCentralWidget(self.centralwidget)
self.retranslateUi(DAQMainWin)
QtCore.QMetaObject.connectSlotsByName(DAQMainWin)
def retranslateUi(self, DAQMainWin):
_translate = QtCore.QCoreApplication.translate
DAQMainWin.setWindowTitle(_translate("DAQMainWin", "IViST"))
self.StartDAQAcquisition.setText(_translate("DAQMainWin", "Start acquisition"))
self.StopDAQAcquisition.setText(_translate("DAQMainWin", "Stop acquisition"))
self.label_1.setText(_translate("DAQMainWin", "Time (s)"))
self.label_2.setText(_translate("DAQMainWin", "DAQ signal (V)"))
from pyqtgraph import PlotWidget
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
DAQMainWin = QtWidgets.QMainWindow()
ui = Ui_DAQMainWin()
ui.setupUi(DAQMainWin)
DAQMainWin.show()
sys.exit(app.exec_())
import nidaqmx
import time
import numpy as np
import warnings
import threading
from nidaqmx.stream_readers import (AnalogSingleChannelReader, AnalogMultiChannelReader)
from nidaqmx.stream_writers import (AnalogSingleChannelWriter, AnalogMultiChannelWriter)
class DAQ_Volt_Tracking(threading.Thread):
"""
Thread that reads an NI DAQ board in continous mode. The NI DAQ samples the signal at 100 kHz. Every 0.1 s, the thread averages 10000 samples.
"""
def __init__(self, daq_path_number: int, input_channels: tuple, output_channels: tuple):
"""
:param : daq_path_number : number of the daq board path position (i.e. 1 for Dev1, 2 for Dev2)
:param : input_channels : analog input channels to use
:param : output_channels : analog output channels to use
"""
# Initiating the thread
super().__init__()
# Creating the tasks
self.read_task = nidaqmx.Task()
self.write_task = nidaqmx.Task()
# Channels parameters
self.number_of_input_channels = len(input_channels)
self.number_of_output_channels = len(output_channels)
self.number_of_samples = 10000
self.sample_rate = 100000
# Adding the channels
for input_channel_number in input_channels:
channel_name = 'Dev{}/ai{}'.format(daq_path_number, input_channel_number)
self.read_task.ai_channels.add_ai_voltage_chan(channel_name, max_val=5, min_val=0)
for output_channel_number in output_channels:
channel_name = 'Dev{}/ao{}'.format(daq_path_number, output_channel_number)
self.write_task.ao_channels.add_ao_voltage_chan(channel_name, max_val=1, min_val=0)
self.values_filename = "raw_voltages.txt"
self.values_file = None
self.values_read = np.zeros((self.number_of_input_channels, self.number_of_samples), dtype=np.float64)
Cont_Mode = nidaqmx.constants.AcquisitionType(10123) # Continious acquisition
self.read_task.timing.cfg_samp_clk_timing(rate=self.sample_rate, samps_per_chan=10000000, sample_mode=Cont_Mode)
self.reader = AnalogMultiChannelReader(self.read_task.in_stream)
self.writer = AnalogMultiChannelWriter(self.write_task.out_stream)
def run(self):
# The function that is called when we start the thread.
self.start_task()
time.sleep(0.1)
self.loop()
def start_task(self):
# Creating the values file
self.values_file = open(self.values_filename, "a")
# Starting tasks
self.read_task.start()
self.write_task.start()
# Writing the gain of the PMT
self.writer.write_one_sample(np.ones(self.number_of_output_channels, dtype=np.float64))
self.start_time = time.time()
self.last_read_time = self.start_time
def loop(self):
self.is_looping = True
self.next_call = time.time()
while self.is_looping:
# Scheduling the next loop call. This is to avoid time drifting.
self.next_call += 0.1
self.reader.read_many_sample(self.values_read, number_of_samples_per_channel=self.number_of_samples, timeout=0.1)
read_time = time.time()
elapsed_time = read_time - self.start_time
time_resolution = read_time - self.last_read_time
# Averaging the 10000 samples
val = np.mean(self.values_read, axis=1)
self.last_read_val = val
try:
self.values_file.write(str(read_time-self.start_time) + ', ')
self.values_file.write(np.array2string(val, separator=',')[1:-1] + '\n')
except Exception as e:
print(e)
self.last_read_time = read_time
#print("Elapsed: {:.3f} Time resolution: {:.3f}".format(elapsed_time, time_resolution))
time.sleep(self.next_call - time.time())
def close(self):
self.is_looping = False
self.writer.write_one_sample(np.zeros(self.number_of_output_channels, dtype=np.float64))
time.sleep(0.1)
warnings.filterwarnings('error')
# Stoping tasks
try:
self.read_task.stop()
self.write_task.stop()
except nidaqmx.errors.DaqWarning:
pass
warnings.filterwarnings('default')
# Closing tasks
self.read_task.close()
self.write_task.close()
# Closing raw data file
self.values_file.close()
# System modules
import numpy as np
from PyQt5 import QtWidgets, QtCore, QtGui
import pyqtgraph as pg
import datetime
import sys
from os.path import join
import queue
import nidaqmx
from nidaqmx.stream_readers import (AnalogSingleChannelReader, AnalogMultiChannelReader)
from nidaqmx.stream_writers import (AnalogSingleChannelWriter, AnalogMultiChannelWriter)
# Local modules
from NI_DAQ.DAQ_Volt_QtDesigner_gui import *
###########################################################
class DAQ_MainWin(QtWidgets.QMainWindow, Ui_DAQMainWin):
def __init__(self, app, signal_queue, *args, **kwargs):
self.start_time = None
self.last_read_time = None
self.signal_queue = signal_queue
self.DAQ_model = 6216
QtWidgets.QMainWindow.__init__(self, *args, **kwargs)
# Getting ready the graph before real time plotting
pg.setConfigOption('background', 'w') # before loading widget
pg.setConfigOption('foreground', 'k')
self.setupUi(self)
app.aboutToQuit.connect(self._closeEvent)
# Connect event to actions
self.c = 0
self.StopDAQAcquisition.clicked.connect(self.stopEvent)
self.StartDAQAcquisition.clicked.connect(self.startAcquisition)
# The Plotter
self.grPlot.plotItem.showGrid(True, True, 0.7)
self.grPlot_2.plotItem.showGrid(True, True, 0.7)
self.grPlot_3.plotItem.showGrid(True, True, 0.7)
self.grPlot_4.plotItem.showGrid(True, True, 0.7)
#self.grPlot.plot([self.a], [Y[0]], pen=None, symbol='o', symbolPen=None, symbolSize=10, symbolBrush=(0, 0, 204))
pen_1 = pg.mkPen(color=(0, 204, 204), width=8)
pen_2 = pg.mkPen(color=(34, 204, 0), width=8)
pen_3 = pg.mkPen(color=(0, 0, 204), width=8)
pen_4 = pg.mkPen(color=(204, 0, 34), width=8)
self.plot_1 = self.grPlot.plot([], [], pen=pen_1)
self.plot_2 = self.grPlot_2.plot([], [], pen=pen_2)
self.plot_3 = self.grPlot_3.plot([], [], pen=pen_3)
self.plot_4 = self.grPlot_4.plot([], [], pen=pen_4)
# Setting a timer
self.timer = pg.QtCore.QTimer()
self.timer.timeout.connect(self.DAQ_loop)
# Initiate DAQ
self.number_of_samples = 10000 # Samples to be collected
self.sample_rate = 100000 # Samples rate production
self.number_of_channels = 4 # Number of channels used during acquisition
self.values_filename = "DAQ_Volt_measurement.txt"
self.values_file = None
self.values_read = np.zeros((self.number_of_channels, self.number_of_samples), dtype=np.float64)
self.t = 0
system = nidaqmx.system.System.local()
Finite_Mode = nidaqmx.constants.AcquisitionType(10178) # Finite acquisition
Cont_Mode = nidaqmx.constants.AcquisitionType(10123) # Continious acquisition
self.write_task = nidaqmx.Task()
self.read_task = nidaqmx.Task()
self.read_task.ai_channels.add_ai_voltage_chan("Dev2/ai11:14", max_val=5, min_val=0)
self.read_task.timing.cfg_samp_clk_timing(rate=self.sample_rate, samps_per_chan=10000000, sample_mode=Cont_Mode)
self.write_task.ao_channels.add_ao_voltage_chan("Dev2/ao0", max_val=1, min_val=0.999)
self.writer = AnalogMultiChannelWriter(self.write_task.out_stream, auto_start=True)
self.reader = AnalogMultiChannelReader(self.read_task.in_stream)
def stopEvent(self):
self.timer.stop()
self.read_task.stop()
self.write_task.stop()
self.values_file.close()
print('--------------------------------------')
print('Stop button pressed')
elapsed = (self.last_read_time - self.start_time).total_seconds()
print("Runtime: {} seconds, {} minutes".format(int(elapsed), int(elapsed / 60)))
def _closeEvent(self):
self.stopEvent()
def startAcquisition(self):
self.values_file = open(self.values_filename, "a")
self.read_task.start()
self.write_task.start()
self.plot_1.setData([], [])
self.plot_2.setData([], [])
self.plot_3.setData([], [])
self.plot_4.setData([], [])
values_to_test = np.ones((1, self.number_of_samples), dtype=np.float64)
self.writer.write_many_sample(values_to_test)
self.start_time = datetime.datetime.now()
self.last_read_time = self.start_time
self.timer.start(20)
def DAQ_loop(self):
###################################################################################################
# If you use cfg_samp_clk_timing set time out as 0.1
self.reader.read_many_sample(self.values_read, number_of_samples_per_channel=self.number_of_samples, timeout=0.1)
read_time = datetime.datetime.now()
elapsed_time = (read_time - self.start_time).total_seconds()
time_resolution = (read_time - self.last_read_time).total_seconds()
val = np.mean(self.values_read, axis=1)
self.signal_queue.put(val)
try:
self.update(elapsed_time, val)
self.values_file.write("{:.3f} {} {} {} {}\n".format(elapsed_time, *val))
except Exception as e:
print(e)
#print("Elapsed: {:.3f} Time resolution: {:.3f}".format(elapsed_time, time_resolution))
self.last_read_time = read_time
def update(self, xval, val, max_nb_val=1000):
xaxis, CH1 = self.plot_1.getData()
_, CH2 = self.plot_2.getData()
_, CH3 = self.plot_3.getData()
_, CH4 = self.plot_4.getData()
xaxis = np.append(xaxis, xval)
CH1 = np.append(CH1, val[0])
CH2 = np.append(CH2, val[1])
CH3 = np.append(CH3, val[2])
CH4 = np.append(CH4, val[3])
xaxis = xaxis[-max_nb_val:]
CH1 = CH1[-max_nb_val:]
CH2 = CH2[-max_nb_val:]
CH3 = CH3[-max_nb_val:]
CH4 = CH4[-max_nb_val:]
self.plot_1.setData(xaxis, CH1)
self.plot_2.setData(xaxis, CH2)
self.plot_3.setData(xaxis, CH3)
self.plot_4.setData(xaxis, CH4)
self.grPlot.setXRange(xval - 5, xval + 5, padding=None)
self.grPlot_2.setXRange(xval - 5, xval + 5, padding=None)
self.grPlot_3.setXRange(xval - 5, xval + 5, padding=None)
self.grPlot_4.setXRange(xval - 5, xval + 5, padding=None)
max1 = max(CH1[-20:]) + 0.4*max(CH1[-20:])
max2 = max(CH2[-20:]) + 0.4*max(CH2[-20:])
max3 = max(CH3[-20:]) + 0.4*max(CH3[-20:])
max4 = max(CH4[-20:]) + 0.4*max(CH4[-20:])
self.grPlot.setYRange(0, max1, padding=None)
self.grPlot_2.setYRange(0, max2, padding=None)
self.grPlot_3.setYRange(0, max3, padding=None)
self.grPlot_4.setYRange(0, max4, padding=None)
if __name__ == "__main__":
queue = queue.LifoQueue()
app = QtWidgets.QApplication([])
window = DAQ_MainWin(app, queue)
window.show()
app.exec_()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment