class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__() self.setWindowTitle('Dissolution DNP Measurement (NSOR project)') self.setWindowIcon( QIcon(BASE_FOLDER + r"\pyqt_analysis\icons\window_icon.png")) ''' --------------------------setting menubar------------------------------- ''' mainMenu = self.menuBar() #create a menuBar fileMenu = mainMenu.addMenu('&File') #add a submenu to the menu bar ''' --------------------------setting toolbar------------------------------- ''' self.toolbar = self.addToolBar( 'nsor_toolbar') #add a tool bar to the window self.toolbar.setIconSize(QSize(100, 100)) self.statusBar() #create a status bar ''' --------------------------setting matplotlib---------------------------- axes are contained in one dictionary ax['time'] ax['freq'] also initiate the vertical lines vline['time_l'] vline['time_r'] vline['freq_l'] vline['freq_r'] ''' if app.desktop().screenGeometry().height() == 2160: matplotlib.rcParams.update({'font.size': 28}) elif app.desktop().screenGeometry().height() == 1080: matplotlib.rcParams.update({'font.size': 14}) canvas = FigureCanvas(Figure(figsize=(50, 15))) self.ax = {} self.vline = {} self.ax['nmr_time'] = canvas.figure.add_subplot(221) self.ax['nmr_freq'] = canvas.figure.add_subplot(222) self.ax['nsor_time'] = canvas.figure.add_subplot(223) self.ax['nsor_freq'] = canvas.figure.add_subplot(224) for axis in self.ax.values(): if app.desktop().screenGeometry().height() == 2160: axis.tick_params(pad=20) elif app.desktop().screenGeometry().height() == 1080: axis.tick_params(pad=10) ''' use pyqtgraph for optical detector because of the fast drawing speed ''' self.optical_graph = pg.PlotWidget() self.optical_data = np.zeros(500) self.optical_data += 1 self.optical_curve = self.optical_graph.plot(self.optical_data) self.optical_graph.setYRange(-0.1, 1.1) print(self.optical_graph.size) ''' --------------------------setting widgets------------------------------- ''' exitProgram = QAction( QIcon(BASE_FOLDER + r'\pyqt_analysis\icons\exit_program.png'), '&Exit', self) exitProgram.setShortcut("Ctrl+W") exitProgram.setStatusTip('Close the Program') exitProgram.triggered.connect(self.exit_program) fileMenu.addAction(exitProgram) editParameters = QAction('&Edit Parameter', self) editParameters.setShortcut('Ctrl+E') editParameters.setStatusTip('open and edit the parameter file') editParameters.triggered.connect(self.edit_parameters) saveParameters = QAction('&Save Parameter', self) saveParameters.setShortcut('Ctrl+S') saveParameters.setStatusTip('save the parameters on screen to file') saveParameters.triggered.connect(self.save_parameters) parameterMenu = mainMenu.addMenu('&Parameter') parameterMenu.addAction(editParameters) parameterMenu.addAction(saveParameters) startExpBtn = QPushButton('START', self) startExpBtn.clicked.connect(self.fluid_detector_read) calibrateBtn = QPushButton('CALIBRATE', self) calibrateBtn.clicked.connect(self.calibrate_fluid_detector) self.readyBtn = QRadioButton('READY', self) self.stopBtn = QPushButton('STOP', self) self.stopBtn.setCheckable(True) injBtn = QPushButton('INJECT', self) injBtn.clicked.connect(lambda: self.switch_mode('inject')) loadBtn = QPushButton('LOAD', self) loadBtn.clicked.connect(lambda: self.switch_mode('load')) ''' --------------------------setting layout/mix widget set----------------- ''' tabs = QTabWidget() tabs.setDocumentMode(True) tabs.setTabPosition(QTabWidget.North) tabs.setMovable(True) tab = {'parameter': QWidget(), 'data': QWidget()} tab_layout = {'parameter': QVBoxLayout(), 'data': QHBoxLayout()} parameter_tab_layout = QFormLayout() sub_tab_layout = {'time': QVBoxLayout(), 'freq': QVBoxLayout()} optical_layout = QHBoxLayout() ''' importing edits from paramter ''' self.edits = {} self.parameters = read_parameter(PARAMETER_FILE) for key, value in self.parameters.items(): if type(value) == list: value = str(value[0]) + ' ' + str(value[1]) self.edits[key] = MyLineEdit(key, value, self) self.edits[key].setStatusTip(f'{key}') if 'nmr' in key: key_str = 'NMR Channel' elif 'nsor' in key: key_str = 'NSOR Channel' else: key_str = key.replace('_', ' ').title() if not ('time' in key or 'freq' in key): ''' parameter tab layout: file_name; pulse_file; samp_rate; iteration; average; pulse_chan; nmr_chan; nsor_chan; laser_chan ''' layout_temp = QHBoxLayout() layout_temp.addWidget(self.edits[key]) if 'file' in key: self.edits[key].setFixedWidth(1250) else: layout_temp.addStretch(1) parameter_tab_layout.addRow(key_str, layout_temp) else: ''' data tab layout: time_x_limit; time_y_limit; freq_x_limit; freq_y_limit; time_cursor; freq_cursor ''' sub_tab_layout[key[0:4]].addWidget(QLabel(key_str, self)) sub_tab_layout[key[0:4]].addWidget(self.edits[key]) if 'freq' in key: self.edits[key].setFixedWidth(250) for key in sub_tab_layout.keys(): sub_tab_layout[key].addStretch(1) tab_layout['parameter'].addLayout(parameter_tab_layout) tab_layout['parameter'].addLayout(optical_layout) button_layout = QVBoxLayout() button_layout.addWidget(injBtn) button_layout.addWidget(loadBtn) button_layout.addWidget(startExpBtn) button_layout.addWidget(self.stopBtn) button_layout.addWidget(calibrateBtn) button_layout.addWidget(self.readyBtn) button_layout.addStretch(1) optical_layout.addLayout(button_layout) optical_layout.addWidget(self.optical_graph) # tab_layout['parameter'].addStretch(1) tab_layout['data'].addLayout(sub_tab_layout['time']) tab_layout['data'].addWidget(canvas) tab_layout['data'].addLayout(sub_tab_layout['freq']) for key in tab.keys(): tabs.addTab(tab[key], key) tab[key].setLayout(tab_layout[key]) _main = QWidget() self.setCentralWidget(_main) layout1 = QVBoxLayout(_main) layout1.addWidget(tabs) ''' --------------------------Multithreading preparation-------------------- ''' self.threadpool = QThreadPool() #Multithreading ''' --------------------------Daqmx Task initialization--------------------- ''' di_line = 'Dev1/port2/line2' self.di_task = Task('di_task') self.di_task.di_channels.add_di_chan(di_line) do_line = 'Dev1/port1/line0, Dev1/port1/line1, Dev1/port1/line5' self.do_task = Task('do_task') self.do_task.do_channels.add_do_chan(do_line) self.do_task.start() ''' -------------------------Menu bar slot---------------------------------- ''' def edit_parameters(self): os.startfile(PARAMETER_FILE) def save_parameters(self): for key in self.parameters.keys(): str = self.edits[key].text() if 'freq' in key or 'time' in key: self.parameters[key] = str.split(' ') else: self.parameters[key] = str save_parameter(PARAMETER_FILE, **self.parameters) def exit_program(self): choice = QMessageBox.question( self, 'Exiting', 'Are you sure about exit?', QMessageBox.Yes | QMessageBox.No) #Set a QMessageBox when called if choice == QMessageBox.Yes: # give actions when answered the question self.do_task.stop() self.di_task.stop() self.do_task.close() self.di_task.close() sys.exit() ''' -------------------------button slots----------------------------------- ''' def switch_mode(self, mode): worker = SwitchValveWorker(self.do_task, mode) self.threadpool.start(worker) ''' --------------------------Multithreading slots-------------------------- ''' def fluid_detector_read(self): worker = FluidDetectorReadWorker(self.di_task, self.optical_data, self.readyBtn, self.stopBtn) worker.signals.detector_triggered.connect(self.collect_data) worker.signals.data.connect(self.update_optical_curve) self.threadpool.start(worker) def update_optical_curve(self, data): self.optical_curve.setData(data) def collect_data(self): if self.stopBtn.isChecked(): self.stopBtn.toggle() else: print('collecting data') # injection time inj_time = int(self.edits['injection_delay'].text()) worker = DataRecorderWorker(self.do_task, inj_time) self.threadpool.start(worker) # self.optical_graph.clear() def calibrate_fluid_detector(self): worker = CalibrateFluidDetectorWorker(self.do_task) self.threadpool.start(worker)
from nidaqmx.task import Task from nidaqmx import constants import numpy as np from numpy import pi import matplotlib.pylab as plt samp_rate = 1000000 duration = 1 sample_num = 1000000 time = np.linspace(0, duration, sample_num) freq = 1000 test_task = Task('ao_test') test_task.ao_channels.add_ao_voltage_chan('/Dev1/ao1') test_task.timing.cfg_samp_clk_timing( rate=samp_rate, #source = '/Dev1/ai/SampleClock', \ samps_per_chan=sample_num, sample_mode=constants.AcquisitionType.CONTINUOUS) pulse_data = np.sin(2 * pi * freq * time) test_task.write(pulse_data) test_task.start() #test_task.wait_until_done() test_task.stop() test_task.close()
class read_writer(): def __init__(self, freq, write_data, sample_rate, number_of_samples): """Function to read and write with the MyDAQ. Write data should be array with length equal to number_of_samples Make sure array does not exceed limits of MyDAQ as no safeguards are built into this function""" #if len(write_data) != number_of_samples: # print("Wrong number of samples passed. Breaking now") # return 0 self.freq = freq self.__define_tasks__(write_data, sample_rate, number_of_samples) self.Nsamples = number_of_samples self.rate = sample_rate def __define_tasks__(self, write_data, sample_rate, number_of_samples): """Here we define the read and write tasks, including their timing""" self.readTask = Task() # Set channel to read from self.readTask.ai_channels.add_ai_voltage_chan( physical_channel='myDAQ1/ai0') self.readTask.ai_channels.add_ai_voltage_chan( physical_channel='myDAQ1/ai1') # Configure timing self.readTask.timing.cfg_samp_clk_timing( rate=sample_rate, samps_per_chan=number_of_samples, sample_mode=constants.AcquisitionType.FINITE) # We define and configure the write task self.writeTask = Task() # Set channel self.writeTask.ao_channels.add_ao_voltage_chan('myDAQ1/ao0') self.writeTask.ao_channels.add_ao_voltage_chan('myDAQ1/ao1') # Set timing self.writeTask.timing.cfg_samp_clk_timing( rate=sample_rate, samps_per_chan=number_of_samples, sample_mode=constants.AcquisitionType.FINITE) self.xarr_fit = np.linspace(0, number_of_samples / sample_rate, number_of_samples) self.yarr_fit = np.sin(2 * np.pi * self.freq * self.xarr_fit) #self.fitfreq = (number_of_samples / sample_rate)/5. #self.fit_data = 3*np.sin(2*np.pi*self.fitfreq*self.xarr_fit) self.writeTask.write([list(self.yarr_fit), list(write_data)]) def __start__(self): """Here we start the writing and reading. We wait until reading is finished and then read the buffer from the DAQ""" self.readTask.start() self.writeTask.start() self.readTask.wait_until_done() self.writeTask.wait_until_done() # Acquire data self.__acquire__() self.__close__() self.__find_phi__() def __close__(self): """Here we shut the tasks explicitly. This function is called from the __start__ function""" # Close connection self.readTask.close() self.writeTask.close() def __acquire__(self): """Read the buffer into attribute self.data""" # Retrieve data self.input = self.readTask.read( number_of_samples_per_channel=self.Nsamples) self.data = self.input[1] self.fit_in = self.input[0] def __fit_call__(self, x, t0): return np.sin(2 * np.pi * self.freq * (x - t0)) def __find_phi__(self): popt, pcov = curve_fit(self.__fit_call__, self.xarr_fit[1000:], self.fit_in[1000:], p0=0, maxfev=int(1e6)) self.t0 = popt[0] def __output__(self): """Return a time array and the data""" # Prepare return data #time_arr = np.linspace(0, self.Nsamples/self.rate, self.Nsamples) t_arr = np.linspace(0, self.Nsamples / self.rate, self.Nsamples) - self.t0 return t_arr, np.array(self.data), self.t0 freqarr = np.logspace(0, 3, 10)