diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d6df762 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +Logs/ +.idea/ +startpycoil.bat +Files/img_rc.pyc +Files/__init__.pyc +Files/Function.pyc +Files/CoilGUI.pyc +Files/Caio_ctype.pyc +startcoil.bat diff --git a/Files/Caio_ctype.py b/Files/Caio_ctype.py new file mode 100644 index 0000000..f8ecf14 --- /dev/null +++ b/Files/Caio_ctype.py @@ -0,0 +1,401 @@ +from ctypes import * +import numpy as np +import time + + +class Caio(object): + # Error handler + def _handle_ret(self, func_name, RET, critical=True): + if RET != 0: + ErrorString = create_string_buffer(256) + Ret2 = self._aio.AioGetErrorString(RET, byref(ErrorString)) + print '%(fname)s = %(err_num)s : %(err_str)s' % \ + {"fname": func_name, "err_num": RET, "err_str": ErrorString.value} + + if critical: + pass + # RET = self._aio.AioExit(self._Id) + + def __init__(self, DeviceName=None): + try: + self._aio = windll.LoadLibrary("caio.dll") + except: + self._aio = windll.LoaAioInitdLibrary("caio32.dll") + + if DeviceName: + self._DeviceName = create_string_buffer(DeviceName) + + self.DeviceName # Gets the device name + self.Id # Initializes the device. + + # Reset device + self.reset_device() + # Defaults + self.memory_type = 'RING' # FIFO also possible + self.n_channels = 3 # set number of output channels to 3 + self.clock_type = 'Internal' # clock_type: 'Internal' or 0 + self.start_trigger = 'Software' + self.stop_trigger = 'Times' # Converting has completed for the specified times + self.repeat_times = 0 # 0=Infinite + + # range: PM10, not configurable on my device + self.set_ao_range_for_channel('all', 'PM10') + + # fs: 1000 + # start_trigger: 'Software' + # stop_trigger: 'Times' + self._max_channels = self.max_chans + + # Reset memory + self.reset_memory() + + def __del__(self): + self.tozero() + #time.sleep(0.01) + RET = self._aio.AioExit(self._Id) + self._handle_ret('AioExit', RET) + + def __exit__(self): + self.tozero() + + # DeviceName + @property + def DeviceName(self): + if not hasattr(self, '_DeviceName') or not self._DeviceName: + self._DeviceName = create_string_buffer(256) + self._Device = create_string_buffer(256) + RET = self._aio.AioQueryDeviceName(c_short(0), byref(self._DeviceName), byref(self._Device)) + self._handle_ret('AioQueryDeviceName', RET) + return self._DeviceName.value + + @DeviceName.setter + def DeviceName(self, value): + pass # Not settable + + # Device or BoardName + @property + def Device(self): + if self.DeviceName and (not hasattr(self, '_Device') or not self._Device): + # We have a _DeviceName but not a _Device + DeviceName = create_string_buffer(256) + self._Device = create_string_buffer(256) + ix = -1 + while DeviceName.value != self.DeviceName: + ix += 1 + RET = self._aio.AioQueryDeviceName(c_short(ix), byref(DeviceName), byref(self._Device)) + self._handle_ret('AioQueryDeviceName', RET, critical=False) + return self._Device.value + + @Device.setter + def Device(self, value): + pass # Not settable. + + # DeviceType + @property + def DeviceType(self): + if not hasattr(self, '_DeviceType') or not self._DeviceType: + self._DeviceType = c_short() + RET = self._aio.AioGetDeviceType(byref(self._Device), byref(self._DeviceType)) + self._handle_ret('AioGetDeviceType', RET) + return self._DeviceType.value + + @DeviceType.setter + def DeviceType(self, value): + pass # Not settable. + + # Id + @property + def Id(self): + if not hasattr(self, '_Id') or not self._Id: + self._Id = c_short() + RET = self._aio.AioInit(self._DeviceName, byref(self._Id)) + self._handle_ret('AioInit', RET) + + return self._Id.value + + # Reset + def reset_status(self): + RET = self._aio.AioResetAoStatus(self._Id) + self._handle_ret('AioResetAoStatus', RET) + + def reset_memory(self): + RET = self._aio.AioResetAoMemory(self._Id) + self._handle_ret('AioResetAoMemory', RET) + + def reset_device(self): + RET = self._aio.AioResetDevice(self._Id) + self._handle_ret('AioResetDevice', RET) + + # Resolution + @property + def n_bits(self): + resolution = c_short() + RET = self._aio.AioGetAoResolution(self._Id, byref(resolution)) + self._handle_ret('AioGetAoResolution', RET) + return resolution.value + + @n_bits.setter + def n_bits(self, value): + pass # read-only + + # Channel + # setaochannels, getaochannels, getaomaxchannels + @property + def max_chans(self): + maxchans = c_short() + RET = self._aio.AioGetAoMaxChannels(self._Id, byref(maxchans)) + self._handle_ret('AioGetAoMaxChannels', RET) + return maxchans.value + + @max_chans.setter + def max_chans(self, value): + pass # read-only + + @property + def n_channels(self): + nchannels = c_short() + RET = self._aio.AioGetAoChannels(self._Id, byref(nchannels)) + self._handle_ret('AioGetAoChannels', RET) + return nchannels.value + + @n_channels.setter + def n_channels(self, value): + nchannels = c_short(np.min((value, self.max_chans))) + RET = self._aio.AioSetAoChannels(self._Id, nchannels) + self._handle_ret('AioSetAoChannels', RET) + + # Range + def get_ao_range_for_channel(self, channel_id=0): + ao_channel = c_short(channel_id) + ao_range = c_short() + RET = self._aio.AioGetAoRange(self._Id, ao_channel, byref(ao_range)) + self._handle_ret('AioGetAoRange', RET) + return ao_range.value + + def set_ao_range_for_channel(self, channel_id='all', AoRange='PM10'): + # Range is fixed to PM10 = -10V to 10V + if AoRange == 'PM10': + ao_range = c_short(0) + elif AoRange == 'PM5': + ao_range = c_short(1) + if channel_id == 'all': + RET = self._aio.AioSetAoRangeAll(self._Id, ao_range) + self._handle_ret('AioSetAoRangeAll', RET) + else: + chan = c_short(channel_id) + RET = self._aio.AioSetAoRange(self._Id, chan, ao_range) + self._handle_ret('AioSetAoRange', RET) + + # Memory Type + @property + def memory_type(self): # proxy for AioGetMemoryType + mem_type = c_short() + RET = self._aio.AioGetAoMemoryType(self._Id, byref(mem_type)) + self._handle_ret('AioGetAoMemoryType', RET) + if mem_type.value == 1: + return 'RING' + elif mem_type.value == 0: + return 'FIFO' + + @memory_type.setter + def memory_type(self, value='FIFO'): # proxy for AioSetAoMemoryType + if value == 'RING': + mem_type = c_short(1) + elif value == 'FIFO': + mem_type = c_short(0) + RET = self._aio.AioSetAoMemoryType(self._Id, mem_type) + self._handle_ret('AioSetAoMemoryType', RET) + + # Repeat + @property + def repeat_times(self): + repeats = c_long() + RET = self._aio.AioGetAoRepeatTimes(self._Id, byref(repeats)) + self._handle_ret('AioGetAoRepeatTimes', RET) + return repeats.value + + @repeat_times.setter + def repeat_times(self, value): # default is 0 = infinite + repeats = c_long(value) + RET = self._aio.AioSetAoRepeatTimes(self._Id, repeats) + self._handle_ret('AioSetAoRepeatTimes', RET) + + # Clock + @property + def clock_type(self): + clock_type = c_short() + RET = self._aio.AioGetAoClockType(self._Id, byref(clock_type)) + self._handle_ret('AioGetAoClockType', RET) + # 0 = Internal, 1=External, 10=Event controller + return {0: 'Internal', 1: 'External', 10: 'Event controller'}.get(clock_type.value) + + @clock_type.setter + def clock_type(self, value='Internal'): + value = {'Internal': 0, 'External': 1, 'Event controller': 10}.get(value) + value = c_short(value) + RET = self._aio.AioSetAoClockType(self._Id, value) + self._handle_ret('AioGetAoClockType', RET) + + @property + def fs(self): + clock = c_float() + RET = self._aio.AioGetAoSamplingClock(self._Id, byref(clock)) + self._handle_ret('AioGetAoSamplingClock', RET) + return 1000000.0 * (1.0 / clock.value) + + @fs.setter + def fs(self, value): + # Passed-in value in Hz. Function wants sample duration in usec. + # e.g. 0.2kHz = 200 samples / sec = 5000 usec per sample + # Usable AoSamplingClock is 10 to 107374182 + clock = c_float(1000000.0 / value) + RET = self._aio.AioSetAoSamplingClock(self._Id, clock) + self._handle_ret('AioSetAoSamplingClock', RET) + + # Setting Data + @property + def buffer(self): + pass + + @buffer.setter + def buffer(self, data): # data is an array of voltage numbers + if data.shape[1] == self.n_channels: + # data=data[:,0:self._max_channels] + # trim excess channels + # --> only 4 columns left for our device (because max_chan=4) / infinte number of rows + n_samples, n_channels = data.shape + # n_samples = number of rows + # n_channels = number of columns + data = np.reshape(data, (n_samples * n_channels,)) + # new array has only one row and ns*nl columns + temp_data = (c_float * (data.shape[0]))() + # data.shape[0] = number of clomuns + # temp_data points to array with the voltage value + for i in range(data.shape[0]): + temp_data[i] = data[i] + # Send every single voltage value to the device according to the memory type + RET = self._aio.AioSetAoSamplingDataEx(self._Id, c_long(n_samples), temp_data) + self._handle_ret('AioSetAoSamplingDataEx', RET) + else: + print('No Execution - Array dimensions do not fit n_channels') + + @property + def sampling_times(self): + ao_sampling_time = c_long() + RET = self._aio.AioGetAoSamplingTimes(self._Id, byref(ao_sampling_time)) + self._handle_ret('AioGetAoSamplingTimes', RET) + return ao_sampling_time.value + + @sampling_times.setter + def sampling_times(self, value): + pass # read-only + + @property + def sampling_count(self): + ao_sampling_count = c_long() + RET = self._aio.AioGetAoSamplingCount(self._Id, byref(ao_sampling_count)) + self._handle_ret('AioGetAoSamplingCount', RET) + return ao_sampling_count.value + + @sampling_count.setter + def sampling_count(self, value): + pass # read-only + + # StartCondition + @property + def start_trigger(self): + trigger = c_short() + RET = self._aio.AioGetAoStartTrigger(self._Id, byref(trigger)) + self._handle_ret('AioGetAoStartTrigger', RET) + return {0: 'Software', 1: 'External trigger rising edge', 2: 'External trigger falling edge', + 10: 'Event controller output'}.get(trigger.value) + + @start_trigger.setter + def start_trigger(self, value='Software'): + value = {'Software': 0, 'External trigger rising edge': 1, 'External trigger falling edge': 2, + 'Event controller output': 10}.get(value) + value = c_short(value) + RET = self._aio.AioSetAoStartTrigger(self._Id, value) + self._handle_ret('AioSetAoStartTrigger', RET) + + # StopCondition + @property + def stop_trigger(self): + trigger = c_short() + RET = self._aio.AioGetAoStopTrigger(self._Id, byref(trigger)) + self._handle_ret('AioGetAoStopTrigger', RET) + return {0: 'Times', 1: 'External trigger rising edge', 2: 'External trigger falling edge', + 10: 'Event controller output'}.get(trigger.value) + + @stop_trigger.setter + def stop_trigger(self, value='Times'): + value = {'Times': 0, 'External trigger rising edge': 1, 'External trigger falling edge': 2, + 'Event controller output': 10}.get(value) + value = c_short(value) + RET = self._aio.AioSetAoStopTrigger(self._Id, value) + self._handle_ret('AioSetAoStopTrigger', RET) + + # disable not available for our device + # def disable_chan(self, channel_id=0): + # ao_channel = c_short(channel_id) + # RET = self._aio.AioDisableAo(self._Id, ao_channel) + # self._handle_ret('AioDisableAo', RET) + + # Action + def start(self): + RET = self._aio.AioStartAo(self._Id) + self._handle_ret('AioStartAo', RET) + + # If FIFO, this will remove data from buffer. + def stop(self): + RET = self._aio.AioStopAo(self._Id) + self._handle_ret('AioStopAo', RET) + + # unclear what MultiAo does + # def multiAo(self, voltage=0): + # self.stop() + # c_chan = c_short(4) + # c_volt = (c_float*1)() + # c_volt[0] = voltage + # print c_volt[0] + # RET=self._aio.AioMultiAoEx(self._Id, c_chan, c_volt) + # self._handle_ret('AioMultiAoEx', RET) + # self.start() + + def tozero(self): + if self.status == 1 or 17: + self.stop() + zero_buffer = np.zeros((1, self.n_channels)) + self.buffer = zero_buffer + self.start() + time.sleep(0.01) + self.stop() + #time.sleep(0.05) + #self.reset_memory() + #time.sleep(0.05) + #self.reset_status() + + # Status + @property + def status(self): # long AioGetAoStatus(short Id, long * AoStatus); + status = c_long() + RET = self._aio.AioGetAoStatus(self._Id, byref(status)) + self._handle_ret('AioGetAoStatus', RET) + return status.value + + # Check that RET==0 + # If RET==7, then execute reset. + @status.setter + def status(self, value): + pass # read-only + + @property + def repeat_count(self): + count = c_long() + RET = self._aio.AioGetAoRepeatCount(self._Id, byref(count)) + self._handle_ret('AioGetAoRepeatCount', RET) + return count.value + + @repeat_count.setter + def repeat_count(self, value): + pass # Read-only diff --git a/Files/CoilGUI.py b/Files/CoilGUI.py new file mode 100644 index 0000000..4d4be33 --- /dev/null +++ b/Files/CoilGUI.py @@ -0,0 +1,504 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'newCoilGUI.ui' +# +# Created by: PyQt4 UI code generator 4.11.4 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName(_fromUtf8("MainWindow")) + MainWindow.resize(875, 506) + self.centralwidget = QtGui.QWidget(MainWindow) + self.centralwidget.setObjectName(_fromUtf8("centralwidget")) + self.formLayout_2 = QtGui.QFormLayout(self.centralwidget) + self.formLayout_2.setObjectName(_fromUtf8("formLayout_2")) + self.gridLayout_11 = QtGui.QGridLayout() + self.gridLayout_11.setObjectName(_fromUtf8("gridLayout_11")) + self.verticalLayout = QtGui.QVBoxLayout() + self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) + self.gridLayout = QtGui.QGridLayout() + self.gridLayout.setObjectName(_fromUtf8("gridLayout")) + self.label = QtGui.QLabel(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) + self.label.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label.setFont(font) + self.label.setObjectName(_fromUtf8("label")) + self.gridLayout.addWidget(self.label, 0, 0, 1, 1) + self.box_bfield = QtGui.QSpinBox(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.box_bfield.sizePolicy().hasHeightForWidth()) + self.box_bfield.setSizePolicy(sizePolicy) + self.box_bfield.setMaximum(100) + self.box_bfield.setProperty("value", 1) + self.box_bfield.setObjectName(_fromUtf8("box_bfield")) + self.gridLayout.addWidget(self.box_bfield, 0, 1, 1, 1) + self.label_2 = QtGui.QLabel(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth()) + self.label_2.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label_2.setFont(font) + self.label_2.setObjectName(_fromUtf8("label_2")) + self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) + self.box_freq = QtGui.QDoubleSpinBox(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.box_freq.sizePolicy().hasHeightForWidth()) + self.box_freq.setSizePolicy(sizePolicy) + self.box_freq.setDecimals(1) + self.box_freq.setMaximum(100.0) + self.box_freq.setSingleStep(0.1) + self.box_freq.setProperty("value", 1.0) + self.box_freq.setObjectName(_fromUtf8("box_freq")) + self.gridLayout.addWidget(self.box_freq, 1, 1, 1, 1) + self.verticalLayout.addLayout(self.gridLayout) + self.btn_start = QtGui.QPushButton(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.btn_start.sizePolicy().hasHeightForWidth()) + self.btn_start.setSizePolicy(sizePolicy) + self.btn_start.setObjectName(_fromUtf8("btn_start")) + self.verticalLayout.addWidget(self.btn_start) + self.btn_stop = QtGui.QPushButton(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.btn_stop.sizePolicy().hasHeightForWidth()) + self.btn_stop.setSizePolicy(sizePolicy) + self.btn_stop.setObjectName(_fromUtf8("btn_stop")) + self.verticalLayout.addWidget(self.btn_stop) + self.lcd_time = QtGui.QLCDNumber(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.lcd_time.sizePolicy().hasHeightForWidth()) + self.lcd_time.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setBold(False) + font.setItalic(False) + font.setWeight(50) + font.setStrikeOut(False) + self.lcd_time.setFont(font) + self.lcd_time.setFrameShape(QtGui.QFrame.StyledPanel) + self.lcd_time.setFrameShadow(QtGui.QFrame.Sunken) + self.lcd_time.setSmallDecimalPoint(False) + self.lcd_time.setNumDigits(8) + self.lcd_time.setSegmentStyle(QtGui.QLCDNumber.Outline) + self.lcd_time.setObjectName(_fromUtf8("lcd_time")) + self.verticalLayout.addWidget(self.lcd_time) + self.btn_close = QtGui.QPushButton(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.btn_close.sizePolicy().hasHeightForWidth()) + self.btn_close.setSizePolicy(sizePolicy) + self.btn_close.setObjectName(_fromUtf8("btn_close")) + self.verticalLayout.addWidget(self.btn_close) + self.gridLayout_11.addLayout(self.verticalLayout, 1, 0, 1, 1) + self.tabWidget = QtGui.QTabWidget(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth()) + self.tabWidget.setSizePolicy(sizePolicy) + self.tabWidget.setTabPosition(QtGui.QTabWidget.North) + self.tabWidget.setTabShape(QtGui.QTabWidget.Rounded) + self.tabWidget.setElideMode(QtCore.Qt.ElideLeft) + self.tabWidget.setUsesScrollButtons(False) + self.tabWidget.setObjectName(_fromUtf8("tabWidget")) + self.fixedDir = QtGui.QWidget() + self.fixedDir.setObjectName(_fromUtf8("fixedDir")) + self.gridLayout_9 = QtGui.QGridLayout(self.fixedDir) + self.gridLayout_9.setObjectName(_fromUtf8("gridLayout_9")) + self.gridLayout_8 = QtGui.QGridLayout() + self.gridLayout_8.setObjectName(_fromUtf8("gridLayout_8")) + self.groupBox_3 = QtGui.QGroupBox(self.fixedDir) + self.groupBox_3.setObjectName(_fromUtf8("groupBox_3")) + self.gridLayout_7 = QtGui.QGridLayout(self.groupBox_3) + self.gridLayout_7.setObjectName(_fromUtf8("gridLayout_7")) + self.x_dir = QtGui.QRadioButton(self.groupBox_3) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.x_dir.setFont(font) + self.x_dir.setChecked(True) + self.x_dir.setObjectName(_fromUtf8("x_dir")) + self.gridLayout_7.addWidget(self.x_dir, 0, 0, 1, 1) + self.y_dir = QtGui.QRadioButton(self.groupBox_3) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.y_dir.setFont(font) + self.y_dir.setObjectName(_fromUtf8("y_dir")) + self.gridLayout_7.addWidget(self.y_dir, 0, 1, 1, 1) + self.z_dir = QtGui.QRadioButton(self.groupBox_3) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.z_dir.setFont(font) + self.z_dir.setObjectName(_fromUtf8("z_dir")) + self.gridLayout_7.addWidget(self.z_dir, 0, 2, 1, 1) + self.neg_dir = QtGui.QCheckBox(self.groupBox_3) + self.neg_dir.setObjectName(_fromUtf8("neg_dir")) + self.gridLayout_7.addWidget(self.neg_dir, 1, 0, 1, 3) + self.gridLayout_8.addWidget(self.groupBox_3, 0, 0, 1, 1) + self.groupBox = QtGui.QGroupBox(self.fixedDir) + self.groupBox.setObjectName(_fromUtf8("groupBox")) + self.gridLayout_4 = QtGui.QGridLayout(self.groupBox) + self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4")) + self.const_field = QtGui.QRadioButton(self.groupBox) + self.const_field.setMaximumSize(QtCore.QSize(16777215, 25)) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.const_field.setFont(font) + self.const_field.setChecked(True) + self.const_field.setObjectName(_fromUtf8("const_field")) + self.gridLayout_4.addWidget(self.const_field, 0, 0, 1, 1) + self.rot_field = QtGui.QRadioButton(self.groupBox) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.rot_field.setFont(font) + self.rot_field.setObjectName(_fromUtf8("rot_field")) + self.gridLayout_4.addWidget(self.rot_field, 1, 0, 1, 1) + self.gridLayout_8.addWidget(self.groupBox, 1, 0, 1, 1) + self.gridLayout_9.addLayout(self.gridLayout_8, 0, 0, 1, 1) + self.tabWidget.addTab(self.fixedDir, _fromUtf8("")) + self.freeDir = QtGui.QWidget() + self.freeDir.setObjectName(_fromUtf8("freeDir")) + self.gridLayout_10 = QtGui.QGridLayout(self.freeDir) + self.gridLayout_10.setObjectName(_fromUtf8("gridLayout_10")) + self.groupBox_2 = QtGui.QGroupBox(self.freeDir) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox_2.sizePolicy().hasHeightForWidth()) + self.groupBox_2.setSizePolicy(sizePolicy) + self.groupBox_2.setObjectName(_fromUtf8("groupBox_2")) + self.gridLayout_5 = QtGui.QGridLayout(self.groupBox_2) + self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5")) + self.verticalLayout_4 = QtGui.QVBoxLayout() + self.verticalLayout_4.setObjectName(_fromUtf8("verticalLayout_4")) + self.horizontalLayout = QtGui.QHBoxLayout() + self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout")) + self.label_3 = QtGui.QLabel(self.groupBox_2) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_3.sizePolicy().hasHeightForWidth()) + self.label_3.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setFamily(_fromUtf8("Symbol")) + font.setPointSize(12) + font.setBold(True) + font.setWeight(75) + self.label_3.setFont(font) + self.label_3.setObjectName(_fromUtf8("label_3")) + self.horizontalLayout.addWidget(self.label_3) + self.ThetaBox = QtGui.QSpinBox(self.groupBox_2) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.ThetaBox.sizePolicy().hasHeightForWidth()) + self.ThetaBox.setSizePolicy(sizePolicy) + self.ThetaBox.setMaximum(180) + self.ThetaBox.setObjectName(_fromUtf8("ThetaBox")) + self.horizontalLayout.addWidget(self.ThetaBox) + self.verticalLayout_4.addLayout(self.horizontalLayout) + self.horizontalLayout_2 = QtGui.QHBoxLayout() + self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2")) + self.label_4 = QtGui.QLabel(self.groupBox_2) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_4.sizePolicy().hasHeightForWidth()) + self.label_4.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setFamily(_fromUtf8("Symbol")) + font.setPointSize(12) + font.setBold(True) + font.setWeight(75) + self.label_4.setFont(font) + self.label_4.setObjectName(_fromUtf8("label_4")) + self.horizontalLayout_2.addWidget(self.label_4) + self.PhiBox = QtGui.QSpinBox(self.groupBox_2) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.PhiBox.sizePolicy().hasHeightForWidth()) + self.PhiBox.setSizePolicy(sizePolicy) + self.PhiBox.setMaximum(360) + self.PhiBox.setObjectName(_fromUtf8("PhiBox")) + self.horizontalLayout_2.addWidget(self.PhiBox) + self.verticalLayout_4.addLayout(self.horizontalLayout_2) + self.label_5 = QtGui.QLabel(self.groupBox_2) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_5.sizePolicy().hasHeightForWidth()) + self.label_5.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label_5.setFont(font) + self.label_5.setObjectName(_fromUtf8("label_5")) + self.verticalLayout_4.addWidget(self.label_5) + self.gridLayout_5.addLayout(self.verticalLayout_4, 0, 0, 1, 1) + self.gridLayout_10.addWidget(self.groupBox_2, 0, 0, 1, 1) + self.tabWidget.addTab(self.freeDir, _fromUtf8("")) + self.scriptDir = QtGui.QWidget() + self.scriptDir.setObjectName(_fromUtf8("scriptDir")) + self.gridLayout_12 = QtGui.QGridLayout(self.scriptDir) + self.gridLayout_12.setObjectName(_fromUtf8("gridLayout_12")) + self.gridLayout_6 = QtGui.QGridLayout() + self.gridLayout_6.setObjectName(_fromUtf8("gridLayout_6")) + self.label_7 = QtGui.QLabel(self.scriptDir) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label_7.setFont(font) + self.label_7.setTextFormat(QtCore.Qt.PlainText) + self.label_7.setObjectName(_fromUtf8("label_7")) + self.gridLayout_6.addWidget(self.label_7, 0, 0, 1, 1) + self.npoints = QtGui.QSpinBox(self.scriptDir) + self.npoints.setMinimum(10) + self.npoints.setMaximum(10000) + self.npoints.setProperty("value", 10) + self.npoints.setObjectName(_fromUtf8("npoints")) + self.gridLayout_6.addWidget(self.npoints, 0, 1, 1, 1) + self.gridLayout_12.addLayout(self.gridLayout_6, 0, 0, 1, 1) + self.label_8 = QtGui.QLabel(self.scriptDir) + self.label_8.setObjectName(_fromUtf8("label_8")) + self.gridLayout_12.addWidget(self.label_8, 1, 0, 1, 1) + self.tabWidget.addTab(self.scriptDir, _fromUtf8("")) + self.DwellScript = QtGui.QWidget() + self.DwellScript.setObjectName(_fromUtf8("DwellScript")) + self.formLayout_4 = QtGui.QFormLayout(self.DwellScript) + self.formLayout_4.setObjectName(_fromUtf8("formLayout_4")) + self.gridLayout_3 = QtGui.QGridLayout() + self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3")) + self.label_9 = QtGui.QLabel(self.DwellScript) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label_9.setFont(font) + self.label_9.setTextFormat(QtCore.Qt.PlainText) + self.label_9.setObjectName(_fromUtf8("label_9")) + self.gridLayout_3.addWidget(self.label_9, 0, 0, 1, 1) + self.npoints_Dwell = QtGui.QSpinBox(self.DwellScript) + self.npoints_Dwell.setMinimum(10) + self.npoints_Dwell.setMaximum(10000) + self.npoints_Dwell.setProperty("value", 10) + self.npoints_Dwell.setObjectName(_fromUtf8("npoints_Dwell")) + self.gridLayout_3.addWidget(self.npoints_Dwell, 0, 1, 1, 1) + self.label_10 = QtGui.QLabel(self.DwellScript) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label_10.setFont(font) + self.label_10.setTextFormat(QtCore.Qt.PlainText) + self.label_10.setObjectName(_fromUtf8("label_10")) + self.gridLayout_3.addWidget(self.label_10, 1, 0, 1, 1) + self.dwelltime = QtGui.QDoubleSpinBox(self.DwellScript) + self.dwelltime.setMinimum(0.1) + self.dwelltime.setMaximum(500.0) + self.dwelltime.setSingleStep(0.1) + self.dwelltime.setProperty("value", 3.0) + self.dwelltime.setObjectName(_fromUtf8("dwelltime")) + self.gridLayout_3.addWidget(self.dwelltime, 1, 1, 1, 1) + self.label_11 = QtGui.QLabel(self.DwellScript) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label_11.setFont(font) + self.label_11.setTextFormat(QtCore.Qt.PlainText) + self.label_11.setObjectName(_fromUtf8("label_11")) + self.gridLayout_3.addWidget(self.label_11, 2, 0, 1, 1) + self.movetime = QtGui.QDoubleSpinBox(self.DwellScript) + self.movetime.setMinimum(0.01) + self.movetime.setMaximum(500.0) + self.movetime.setSingleStep(0.1) + self.movetime.setProperty("value", 0.5) + self.movetime.setObjectName(_fromUtf8("movetime")) + self.gridLayout_3.addWidget(self.movetime, 2, 1, 1, 1) + self.formLayout_4.setLayout(0, QtGui.QFormLayout.LabelRole, self.gridLayout_3) + self.formLayout = QtGui.QFormLayout() + self.formLayout.setObjectName(_fromUtf8("formLayout")) + self.calc_scripttime = QtGui.QLabel(self.DwellScript) + self.calc_scripttime.setObjectName(_fromUtf8("calc_scripttime")) + self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.calc_scripttime) + self.label_12 = QtGui.QLabel(self.DwellScript) + self.label_12.setObjectName(_fromUtf8("label_12")) + self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_12) + self.formLayout_4.setLayout(1, QtGui.QFormLayout.LabelRole, self.formLayout) + self.formLayout_3 = QtGui.QFormLayout() + self.formLayout_3.setObjectName(_fromUtf8("formLayout_3")) + self.radBut_Dwell_XY = QtGui.QRadioButton(self.DwellScript) + self.radBut_Dwell_XY.setObjectName(_fromUtf8("radBut_Dwell_XY")) + self.formLayout_3.setWidget(0, QtGui.QFormLayout.LabelRole, self.radBut_Dwell_XY) + self.radBut_Dwell_Sphere = QtGui.QRadioButton(self.DwellScript) + self.radBut_Dwell_Sphere.setEnabled(True) + self.radBut_Dwell_Sphere.setChecked(True) + self.radBut_Dwell_Sphere.setObjectName(_fromUtf8("radBut_Dwell_Sphere")) + self.formLayout_3.setWidget(1, QtGui.QFormLayout.LabelRole, self.radBut_Dwell_Sphere) + self.formLayout_4.setLayout(2, QtGui.QFormLayout.LabelRole, self.formLayout_3) + self.tabWidget.addTab(self.DwellScript, _fromUtf8("")) + self.gridLayout_11.addWidget(self.tabWidget, 0, 0, 1, 1) + self.formLayout_2.setLayout(0, QtGui.QFormLayout.LabelRole, self.gridLayout_11) + self.gridLayout_2 = QtGui.QGridLayout() + self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) + self.label_status = QtGui.QLabel(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_status.sizePolicy().hasHeightForWidth()) + self.label_status.setSizePolicy(sizePolicy) + self.label_status.setAutoFillBackground(True) + self.label_status.setObjectName(_fromUtf8("label_status")) + self.gridLayout_2.addWidget(self.label_status, 2, 0, 1, 1) + self.label_field = QtGui.QLabel(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_field.sizePolicy().hasHeightForWidth()) + self.label_field.setSizePolicy(sizePolicy) + self.label_field.setMinimumSize(QtCore.QSize(200, 200)) + font = QtGui.QFont() + font.setFamily(_fromUtf8("Arial")) + font.setPointSize(14) + font.setBold(True) + font.setWeight(75) + self.label_field.setFont(font) + self.label_field.setFrameShape(QtGui.QFrame.StyledPanel) + self.label_field.setText(_fromUtf8("")) + self.label_field.setAlignment(QtCore.Qt.AlignCenter) + self.label_field.setObjectName(_fromUtf8("label_field")) + self.gridLayout_2.addWidget(self.label_field, 1, 0, 1, 1) + self.label_6 = QtGui.QLabel(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_6.sizePolicy().hasHeightForWidth()) + self.label_6.setSizePolicy(sizePolicy) + self.label_6.setObjectName(_fromUtf8("label_6")) + self.gridLayout_2.addWidget(self.label_6, 0, 0, 1, 1) + self.text_status = QtGui.QTextBrowser(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.text_status.sizePolicy().hasHeightForWidth()) + self.text_status.setSizePolicy(sizePolicy) + self.text_status.setObjectName(_fromUtf8("text_status")) + self.gridLayout_2.addWidget(self.text_status, 3, 0, 1, 1) + self.formLayout_2.setLayout(0, QtGui.QFormLayout.FieldRole, self.gridLayout_2) + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QtGui.QMenuBar(MainWindow) + self.menubar.setGeometry(QtCore.QRect(0, 0, 875, 21)) + self.menubar.setObjectName(_fromUtf8("menubar")) + self.menuFile = QtGui.QMenu(self.menubar) + self.menuFile.setObjectName(_fromUtf8("menuFile")) + self.menuCalibration = QtGui.QMenu(self.menubar) + self.menuCalibration.setObjectName(_fromUtf8("menuCalibration")) + self.menuSpherical_Coordinates = QtGui.QMenu(self.menubar) + self.menuSpherical_Coordinates.setObjectName(_fromUtf8("menuSpherical_Coordinates")) + MainWindow.setMenuBar(self.menubar) + self.statusbar = QtGui.QStatusBar(MainWindow) + self.statusbar.setObjectName(_fromUtf8("statusbar")) + MainWindow.setStatusBar(self.statusbar) + self.menu_calib = QtGui.QAction(MainWindow) + self.menu_calib.setObjectName(_fromUtf8("menu_calib")) + self.menu_close = QtGui.QAction(MainWindow) + self.menu_close.setObjectName(_fromUtf8("menu_close")) + self.manue_newcalib = QtGui.QAction(MainWindow) + self.manue_newcalib.setObjectName(_fromUtf8("manue_newcalib")) + self.actionShow_drawing = QtGui.QAction(MainWindow) + self.actionShow_drawing.setObjectName(_fromUtf8("actionShow_drawing")) + self.menuFile.addAction(self.menu_close) + self.menuCalibration.addAction(self.menu_calib) + self.menuCalibration.addAction(self.manue_newcalib) + self.menuSpherical_Coordinates.addAction(self.actionShow_drawing) + self.menubar.addAction(self.menuFile.menuAction()) + self.menubar.addAction(self.menuCalibration.menuAction()) + self.menubar.addAction(self.menuSpherical_Coordinates.menuAction()) + + self.retranslateUi(MainWindow) + self.tabWidget.setCurrentIndex(3) + QtCore.QObject.connect(self.btn_start, QtCore.SIGNAL(_fromUtf8("released()")), self.label_status.update) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) + self.label.setText(_translate("MainWindow", "B-Field (Gauss)", None)) + self.label_2.setText(_translate("MainWindow", "Frequency (Hz)", None)) + self.btn_start.setText(_translate("MainWindow", "Start", None)) + self.btn_stop.setText(_translate("MainWindow", "Stop", None)) + self.btn_close.setText(_translate("MainWindow", "Save Logfile and Close", None)) + self.groupBox_3.setTitle(_translate("MainWindow", "Fixed direction", None)) + self.x_dir.setText(_translate("MainWindow", "X", None)) + self.y_dir.setText(_translate("MainWindow", "Y", None)) + self.z_dir.setText(_translate("MainWindow", "Z", None)) + self.neg_dir.setText(_translate("MainWindow", "Negative Direction", None)) + self.groupBox.setTitle(_translate("MainWindow", "Field mode", None)) + self.const_field.setText(_translate("MainWindow", "constant field", None)) + self.rot_field.setText(_translate("MainWindow", "rotating field", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.fixedDir), _translate("MainWindow", "Fixed direction", None)) + self.groupBox_2.setTitle(_translate("MainWindow", "Free direction", None)) + self.label_3.setText(_translate("MainWindow", "q", None)) + self.label_4.setText(_translate("MainWindow", "f", None)) + self.label_5.setText(_translate("MainWindow", "only constant fields ! Frequency has no effect", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.freeDir), _translate("MainWindow", "Free direction", None)) + self.label_7.setText(_translate("MainWindow", "Number of points on unit sphere", None)) + self.label_8.setText(_translate("MainWindow", "

Script for "Random/Brownian Motion"

Set the number of points being randomly
distributed on a sphere with radius B.
Sampling rate is specified by the frequency from below.

", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.scriptDir), _translate("MainWindow", "Continuous Script", None)) + self.label_9.setText(_translate("MainWindow", "Number of points on unit sphere", None)) + self.label_10.setText(_translate("MainWindow", "Dwell time", None)) + self.label_11.setText(_translate("MainWindow", "Move time", None)) + self.calc_scripttime.setText(_translate("MainWindow", "0", None)) + self.label_12.setText(_translate("MainWindow", "Script length with current parameters (s)", None)) + self.radBut_Dwell_XY.setText(_translate("MainWindow", "Rotation in XY", None)) + self.radBut_Dwell_Sphere.setText(_translate("MainWindow", "Sphere script", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.DwellScript), _translate("MainWindow", "Dwell Script", None)) + self.label_status.setText(_translate("MainWindow", "Status", None)) + self.label_6.setText(_translate("MainWindow", "Coil status", None)) + self.menuFile.setTitle(_translate("MainWindow", "File", None)) + self.menuCalibration.setTitle(_translate("MainWindow", "Properties", None)) + self.menuSpherical_Coordinates.setTitle(_translate("MainWindow", "Spherical Coordinates", None)) + self.menu_calib.setText(_translate("MainWindow", "Choose calibration", None)) + self.menu_close.setText(_translate("MainWindow", "Save Log & Close", None)) + self.manue_newcalib.setText(_translate("MainWindow", "Set new calibration", None)) + self.actionShow_drawing.setText(_translate("MainWindow", "Definition", None)) + +import img_rc diff --git a/Files/CoilGUI.ui b/Files/CoilGUI.ui new file mode 100644 index 0000000..5a4e31f --- /dev/null +++ b/Files/CoilGUI.ui @@ -0,0 +1,290 @@ + + + MainWindow + + + + 0 + 0 + 672 + 472 + + + + MainWindow + + + + + + + + + Signal + + + + + + + + constant field + + + true + + + + + + + rotating field + + + + + + + + + + + + Direction + + + + + + + + x + + + true + + + + + + + y + + + + + + + z + + + + + + + Negative Direction + + + + + + + + + + + + + + + + + + B-Field (Gauss) + + + + + + + 360 + + + + + + + Frequency + + + + + + + 360 + + + + + + + + + + + Stop + + + + + + + Start + + + + + + + + + + + + + true + + + Status + + + + + + + + + + + + Qt::Vertical + + + + + Arial + 14 + 75 + true + + + + QFrame::StyledPanel + + + + + + Qt::AlignCenter + + + + + + + + Save Logfile and Close + + + + + + + + 50 + false + false + false + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + false + + + 8 + + + QLCDNumber::Outline + + + + + + + + + 0 + 0 + 672 + 21 + + + + + File + + + + + + Properties + + + + + + + + + + + Choose calibration + + + + + Save Log & Close + + + + + Set new calibration + + + + + + + btn_start + released() + label_status + update() + + + 71 + 46 + + + 153 + 397 + + + + + diff --git a/Files/Function.py b/Files/Function.py new file mode 100644 index 0000000..7de6182 --- /dev/null +++ b/Files/Function.py @@ -0,0 +1,225 @@ +# -*- coding: utf-8 -*- +""" +Created on Thu Sep 08 15:39:44 2016 + +@author: admin_lab +""" + + +import numpy as np +import warnings +import os +import mpl_toolkits.mplot3d +import matplotlib.pyplot as pp + +np.set_printoptions(precision=4) + +warnings.simplefilter(action = "ignore", category = FutureWarning) + + + + +def sinewave(frequency=1.0, offset=0, samples=1000.0): + samples=samples/frequency + t = np.linspace(0,2*np.pi,samples) + y = np.sin(t+offset*np.pi/180)[:,None] + return y + +# #if caio.get_ao_range_for_channel() == 0: ao_range=10.0 +# #only 10V ao_range possible for our device +# ao_range=10.0 +# actual_s = self.sampling_count +# fs = self.fs +# actual_volt = ao_range * actual_s/fs + +def constant(amplitude=0.0): + return amplitude*np.ones((1, 1)) + +def writebuffer(x=None, y=None, z=None): + empty = np.zeros((1,1)) + a = type(empty) + rows = np.shape(empty)[0] + + if x is None: x = empty + if y is None: y = empty + if z is None: z = empty + + v= x, y, z + + + + #check if x,y,z are arrays + if any([type(i) != a for i in v]): + print 'writebuffer(x,y,z): Input arguments must be arrays of same length' + return 'Error' + + # no argument >> return only zeros + if all([np.array_equal(i, empty) for i in v]): + return np.hstack((empty,empty,empty)) + else: + #use rows from non-empty argument + for i in v: + if not (np.array_equal(i, empty)): + rows = np.shape(i)[0] + #and append zeros if no argument is given + for i in v: + if (np.array_equal(i, empty)): + i.resize((rows,1), refcheck=False) + + + if (np.shape(x) != np.shape(y)) or (np.shape(y) != np.shape(z)) or (np.shape(z) != np.shape(x)): + print 'writebuffer(): Shape of the input arrays differ:' + return 'Error' + else: + return np.hstack((x,y,z)) + + +def direction(axis, mode, amp=1.0, freq=1.0, samp=1000.0, calibration=[0.01,0.01,0.01]): + + #use list with calibration factors [x,y,z] + x_cal = calibration[0] + y_cal = calibration[1] + z_cal = calibration[2] + + + #calculate sine signals + if (mode =='rotate'): + a = amp*sinewave(frequency=freq, offset=0, samples=samp) + b = amp*sinewave(frequency=freq, offset=90, samples=samp) + b_neg = amp*sinewave(frequency=freq, offset=270, samples=samp) + + #return signals + if (axis == 'x'): + if (mode == 'constant'): + return writebuffer(x=constant(x_cal*amp)) + elif (mode == 'rotate'): + return writebuffer(y=y_cal*a,z=z_cal*b) + if (axis == '-x'): + if (mode == 'constant'): + return writebuffer(x=constant(x_cal*(-1)*amp)) + elif (mode == 'rotate'): + return writebuffer(y=y_cal*a,z=z_cal*b_neg) + + if (axis == 'y'): + if (mode == 'constant'): + return writebuffer(y=constant(y_cal*amp)) + elif (mode == 'rotate'): + return writebuffer(x=x_cal*a,z=z_cal*b) + if (axis == '-y'): + if (mode == 'constant'): + return writebuffer(y=constant(y_cal*(-1)*amp)) + elif (mode == 'rotate'): + return writebuffer(x=x_cal*a,z=z_cal*b_neg) + + if (axis == 'z'): + if (mode == 'constant'): + return writebuffer(z=constant(z_cal*amp)) + elif (mode == 'rotate'): + return writebuffer(x=x_cal*a, y=y_cal*b) + if (axis == '-z'): + if (mode == 'constant'): + return writebuffer(z=constant(z_cal*(-1)*amp)) + elif (mode == 'rotate'): + return writebuffer(x=x_cal*a,y=y_cal*b_neg) + + else: + print 'direction(): Input wrong, use string as axis and mode' + return writebuffer(constant(0)) + + +def list_f_ext(directory, extension): + out=[] + for f in os.listdir(directory): + if f.endswith('.' + extension): + out.append(f) + return out + + +def spherical_points(npoints, ndim=3): + # create random points on unit sphere + vec = np.random.randn(ndim, npoints) + vec /= np.linalg.norm(vec, axis=0) + return vec.T + +def golden_spiral(num_pts=100): + # Derived from the golden spiral method from + # https://stackoverflow.com/questions/9600801/evenly-distributing-n-points-on-a-sphere + # ----------- + # IMPORTANT: theta and phi are swapped sometimes + # +++++++ NOW IN PHYSICAL/ISO COORDINATES ++++++++++ + # ----------- + + # subtract two points from the trajectory to manually insert theta/phi = (0,0) in the end + # num_pts -= 2 + #create indices + indices = np.arange(0, num_pts, dtype=float) + 0.5 + #create theta and phi + theta = np.arccos(1 - 2*indices/num_pts) #from 0 ti Pi + phi = np.mod((1 + 5**0.5) * indices, 2*np.pi) #from 0 to 2Pi + + #calculate x,y,z + x = np.cos(phi) * np.sin(theta) + y = np.sin(phi) * np.sin(theta) + z = np.cos(theta) + + #create a trajectory with connecting "nearest" neighbor point + vec = np.vstack((x, y, z)).T.round(15) + v1= vec[1::2] #rows with odd indices + v2 = vec[::2] #rows with even indices + backandforth = np.vstack((v1, v2[::-1])) #stack v2 in reversed order to avoid jumping + + #get theta phi + thetaphi = np.vstack((theta, phi)).T.round(15) + tp1= thetaphi[1::2] #rows with odd indices + tp2 = thetaphi[::2] #rows with even indices + thetaphi = np.vstack((tp1, tp2[::-1])) #stack v2 in reversed order to avoid jumping + + # #manually add theta=phi=0 and theta=180, phi=0 --> (x, y, z)==(0,0,1) or (0,0,-1) + # thetaphi = np.insert(thetaphi, 0, [0,0], 0) + # backandforth = np.insert(backandforth, 0, [0,0,1], 0) + # halfidx=(num_pts/2) + # thetaphi = np.insert(thetaphi, halfidx, [0,np.pi] ,0) + # backandforth = np.insert(backandforth, halfidx, [0,0,-1], 0) + + # #this would be a vector with a trajectory going bck and forth + # field = vec.repeat(2, axis=0) + # field[::2] = [0, 0, 0] + # #-- plot trajectory 1 and two -- + # pp.figure().add_subplot(111, projection='3d').plot(v1[:,0], v1[:,1], v1[:,2], 'o-') + # pp.figure().add_subplot(111, projection='3d').plot(v2[:,0], v2[:,1], v2[:,2], 'o-') + # #----------- plot scatter-line of full trajectory and field vector --------- + # pp.figure().add_subplot(111, projection='3d').plot(backandforth[:, 0], backandforth[:, 1], backandforth[:, 2], 'o-') + # pp.title('trajectory for n=%d points' % (num_pts)) + # pp.figure().add_subplot(111, projection='3d').plot(field[:, 0], field[:, 1], field[:, 2], 'r-') + # pp.title('orientation of field vector') + # pp.show() + # + # np.savetxt("C:\Users\sachs\testraw_N" + str(num_pts) + ".csv", np.hstack((thetaphi, backandforth)), delimiter=",") + + return backandforth + + +def traj_on_sphere(npoints): + #not evenly distirbuted! + pts = np.zeros((npoints,3)) + + theta = np.deg2rad(np.linspace(0,180,npoints/2)) #half sphere would be 0-90deg + phi = np.deg2rad(np.linspace(0,360,npoints/2)) + + cnt=0 + for the_tmp in theta: + for phi_tmp in phi: + x = np.sin(theta) * np.cos(phi) + y = np.sin(theta) * np.sin(phi) + z = np.cos(theta) + + pts[cnt, :] = np.hstack((x,y,z)) + cnt+=1 + return pts + +def circleXY(n_points): + x=sinewave(frequency=1.0, offset=0, samples=n_points) + y=sinewave(frequency=1.0, offset=90, samples=n_points) + z=np.zeros((n_points,1)) + ptsXYZ=np.hstack((x,y, z)) + return ptsXYZ diff --git a/Files/__init__.py b/Files/__init__.py new file mode 100644 index 0000000..2d810dc --- /dev/null +++ b/Files/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +""" +Created on Wed Sep 07 15:45:36 2016 + +@author: js-phys +""" + diff --git a/Files/img.qrc b/Files/img.qrc new file mode 100644 index 0000000..70e32f0 --- /dev/null +++ b/Files/img.qrc @@ -0,0 +1,5 @@ + + + spherCoo.png + + diff --git a/Files/img_rc.py b/Files/img_rc.py new file mode 100644 index 0000000..12599ea --- /dev/null +++ b/Files/img_rc.py @@ -0,0 +1,326 @@ +# -*- coding: utf-8 -*- + +# Resource object code +# +# Created by: The Resource Compiler for PyQt5 (Qt v5.9.3) +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore + +qt_resource_data = b"\ +\x00\x00\x10\xd7\ +\x89\ +\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ +\x00\x00\xee\x00\x00\x00\xdf\x08\x04\x00\x00\x00\x5b\xc1\x27\xa1\ +\x00\x00\x00\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\ +\x00\x09\x70\x48\x59\x73\x00\x00\x00\x6e\x00\x00\x00\x6e\x00\x54\ +\xe2\x0e\x31\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xe2\x04\x08\x10\ +\x14\x07\x0b\x80\x7f\x80\x00\x00\x0f\x7c\x49\x44\x41\x54\x78\xda\ +\xed\x9d\xcf\xab\xfc\xdc\x5d\xc7\x5f\x9f\xc7\x8a\x54\xab\x10\xb4\ +\x20\x88\x0b\xf3\xb5\xea\xa6\x28\xcd\xfd\x03\x5c\xe4\x82\x1b\xc1\ +\x4d\xee\xc6\x4d\x41\xc8\xb4\x08\x82\x48\x9d\x01\x97\x8a\x66\x16\ +\x75\xe1\x2e\xb3\xe9\xaa\x94\xce\x05\x79\x5c\x67\xc0\x76\x23\x5d\ +\x4c\x5c\x88\xd2\x45\x3b\x69\x71\x55\x4a\x7b\x83\xf5\x59\x3c\x0f\ +\xcf\x83\x1f\x17\x93\x7b\xef\xcc\xdc\xf9\x99\x9c\x4c\x92\x33\xe7\ +\x9d\xc5\xfc\x4c\x72\x32\xaf\xf9\x7c\xce\x39\x9f\x7c\xce\x39\xa2\ +\x38\xd9\xaa\xf7\xba\x2e\xc0\x71\x89\x27\x41\xd7\x65\x18\xae\x7a\ +\x0e\x97\x80\xa4\xeb\x22\x0c\x57\x7d\x87\xeb\xd4\x40\x0e\xae\xc5\ +\x72\x70\x2d\x96\x83\x6b\xb1\x1c\x5c\x8b\xe5\xe0\x5a\x2c\x07\xd7\ +\x62\x39\xb8\x16\xcb\xc1\xb5\x58\x0e\xae\xc5\x72\x70\x2d\x96\x83\ +\x6b\xb1\x1c\x5c\x8b\xe5\xe0\x5a\x2c\x07\xd7\x62\x39\xb8\x16\xcb\ +\xc1\xb5\x58\x0e\xae\xc5\x72\x70\x2d\x96\x83\x6b\xb1\x1c\x5c\x8b\ +\xe5\xe0\x5a\x2c\x07\xd7\x62\xf5\x1d\xee\x67\xf8\x54\xd7\x45\x18\ +\xae\x7a\x02\x57\x52\x49\x24\x91\x27\xd9\x4d\x41\xff\x1c\x5f\x70\ +\x63\x0e\xea\xaa\x27\x70\x99\xea\x04\x58\xe8\xe4\xcd\x27\x9f\xe6\ +\xab\xf2\xe5\xae\x8b\x37\x4c\xf5\x04\xae\x16\x12\x12\x32\xda\xf3\ +\xd1\xcf\xf8\x2b\xfe\x4c\xe6\xe2\x75\x5d\xc6\xe1\xa9\x27\x70\xc5\ +\x27\xe5\x41\xcb\x7d\x2e\x58\x73\xee\x29\x59\x3a\xf7\x7c\xa9\x7a\ +\x02\x97\x39\x39\xb1\x24\xf8\xfb\x3e\xd4\x52\x47\x4c\xc8\xc4\x0d\ +\x0a\xbb\x48\x3d\x69\x8b\xea\xdd\xc9\x6f\x3c\x4a\xce\x5c\x32\x1e\ +\xb4\xec\xba\xb4\x43\x51\x5f\x2c\xf7\x0c\x69\xa1\x77\xe4\xac\x24\ +\xec\xba\x24\x43\xd1\x80\xe0\x02\xe8\x84\x07\xe6\xce\x3d\x9f\xa7\ +\x81\xc1\x05\x5d\xf0\x8e\x40\x96\xe2\x37\x3f\x96\xed\x1a\x1c\x5c\ +\xd0\x52\xef\x59\xb0\x94\xa8\xeb\x92\xf4\x5d\x03\x84\x0b\xa0\x13\ +\xee\x49\x24\x75\xbd\xdf\x63\x1a\x28\x5c\xd0\x9c\x3b\x3c\x32\xd7\ +\xfb\x3d\xac\xc1\xc2\x05\x2d\xf5\x81\x47\xe6\x32\xee\xba\x24\x7d\ +\xd5\x80\xe1\x02\xe8\x94\x07\x22\x17\x9c\xdc\xaf\x81\xc3\x75\xc1\ +\xc9\x63\x1a\x3c\x5c\x17\x9c\x3c\x2c\x0b\xe0\x02\xe8\x23\x77\x84\ +\x92\x39\xf7\xbc\x29\x4b\xe0\xba\xe0\xe4\x3e\x59\x03\x17\x5c\x70\ +\x72\x57\x56\xc1\x75\xc1\xc9\x6d\x59\x06\xd7\x05\x27\x37\x65\x1d\ +\x5c\xb8\x4e\x70\x52\x02\x13\xde\xa1\xdd\x00\x8c\x95\x70\xdb\x0f\ +\x4e\x4a\x40\xa2\x85\x91\x23\xb5\xd9\x42\xd0\x5e\x6f\x7c\x85\x9f\ +\x34\xd8\x7b\xcc\x8a\x71\x2b\xe5\x5a\xe1\x1b\x3a\xd2\x92\xa0\xad\ +\x5f\xcf\x52\xcb\xad\xfe\xb8\x2d\x05\x27\x25\x66\x61\xc6\x6e\x81\ +\x19\x71\x5b\xd7\x6f\x35\xdc\xd6\x82\x93\x01\xf9\xfa\x89\x78\x92\ +\xc8\x58\x02\x49\x76\x1b\x70\x12\x49\x22\x1e\x48\xf0\xb6\x69\x27\ +\x63\x89\x40\xd6\x50\x1f\x69\xad\xe9\x67\x39\xdc\x96\x82\x93\x01\ +\x05\x80\x78\xcc\x99\x11\x31\x07\xd2\xcd\x2f\x48\x48\x80\x4f\x0c\ +\xc4\xec\x84\x55\x24\xc1\x67\x2c\xd9\x3a\xd3\x53\x4b\xca\xd6\x3a\ +\x6e\x5d\xd7\xaa\x6d\xd6\xb9\x1b\xc7\xf1\x59\x92\xe1\x19\x2a\x95\ +\x56\x8f\x11\xa1\x42\xc6\x18\x7f\xbb\xe6\x24\xc6\xe3\x89\x50\x61\ +\x45\xbc\x5b\x16\x85\x98\xf4\xe5\x75\x46\xd8\xd2\xaf\xd7\x35\xbe\ +\xeb\xc0\x55\x14\x92\xf5\xcf\x6d\x0e\xee\xcb\x4f\xb8\xa7\x49\x44\ +\xc4\x4a\xc1\x47\xdf\x36\xbd\x36\xd1\xb6\x09\xd7\x7a\xb7\xbc\xe1\ +\xa3\xcc\x05\x27\xf3\x75\x1d\x2e\xbe\xf8\x12\x52\x6a\x2e\xbe\xc4\ +\x20\xde\x86\x83\x0d\x58\x00\x21\xb9\x16\x20\xfe\x6b\xa3\x4e\x62\ +\xd0\xd1\x7a\x0f\x00\x3c\x5a\xca\xc4\xbe\x21\xb8\x06\x83\x93\x39\ +\xeb\x06\x5a\xca\x98\x88\x42\x3c\xc6\x2c\x80\x84\xd5\x0b\xc4\x12\ +\xc4\x23\x66\x01\xc0\xea\x79\x09\x1d\x89\x89\x89\x24\x25\xab\x3e\ +\x81\x40\xf3\x76\xae\xf7\xa6\xe0\x1a\x0b\x4e\x3e\xc3\x9d\x51\xf2\ +\xc8\x8c\x31\x33\x2d\x80\x19\x8b\x97\x01\x31\x33\x0a\xc6\xf8\x55\ +\xbb\xfa\x75\x88\x5b\xa9\x77\x4c\x28\x79\x58\x77\xa6\x24\xe2\xb1\ +\xbd\xcb\xed\xf5\x66\xb2\xce\xdd\x38\x6a\xc0\x8a\xb4\x7e\xf3\x0a\ +\x8f\xa7\xfd\x7b\x33\x7f\x39\x83\xe2\x13\xb3\xac\x5e\xfb\x24\x07\ +\x8e\xd5\x5a\x8d\x7b\x53\x75\xee\xc6\x1f\xba\x61\x70\x52\x4b\x46\ +\xdb\x5d\x9f\xb5\x24\x7a\x71\xb5\x25\x39\x31\x11\x0f\xd5\xeb\x31\ +\xd3\x7d\x47\x92\x98\x42\x17\xb4\xa5\xae\x6d\xb3\x0b\xcb\xad\x8e\ +\xdd\x28\x38\x49\x6c\x22\x6c\x78\xc8\x9e\xcd\x6c\xd2\xef\x55\x38\ +\xe5\x2b\x8c\xf5\xd7\x5a\x3b\x7a\x40\x4a\xc1\xc8\xd6\x71\x83\x37\ +\xe9\x96\x9f\x65\x7b\xe6\xe4\x4d\xc3\xb5\x3d\x73\xf2\xc6\xe1\x82\ +\xcd\x99\x93\x0e\x2e\xf6\x66\x4e\x3a\xb8\x95\x6c\xcc\x9c\x74\x70\ +\x5f\x64\x5f\xe6\xa4\x83\xbb\x21\xdb\x32\x27\x1d\xdc\x1d\xd9\x34\ +\xac\xdb\xc1\x7d\xa3\xcd\xe0\xa4\x78\xf2\x77\xf2\x0d\xf9\xf3\x81\ +\xa2\xee\x3a\xc0\xd8\x5d\xf8\xf1\x8c\xe0\xe4\xfb\xfc\x4f\xf5\xf2\ +\xc7\xfc\x61\xd7\xbf\xc5\xe5\x9b\xb3\xdc\x03\xd2\x29\x7f\xc9\x1f\ +\xf3\x2b\xd5\xcb\xcf\xf2\xcf\xc7\xad\xd7\x44\x7a\xb9\x84\x66\x63\ +\x65\x7d\x87\xfb\x7f\x7c\xd4\xd9\xb9\xbf\xbc\xf5\xeb\x78\x1c\x99\ +\x3b\xf6\x74\x17\x4a\x3c\x49\x25\x93\x03\x69\xac\xd5\xfb\x39\x89\ +\x49\xbc\x7d\x87\xfb\x1e\xbf\xd0\xd9\xb9\x7f\x6f\xe7\xf5\xe7\x0f\ +\x7d\x51\x42\x02\x9d\x9e\x38\x5a\x46\xc1\x03\x87\xfe\x04\x01\x80\ +\x96\x4c\x31\xd8\xd3\xee\x3b\xdc\x2e\xf5\xb3\x9d\xd7\x1f\x1c\xfc\ +\x66\xcc\x09\xb4\x12\xe3\xe9\x54\x4b\x4e\x34\xcc\x74\x01\xe6\x6c\ +\xd7\xc1\x3d\xac\xd9\xd6\xab\x8f\xf8\x87\x83\xdf\x8c\x36\x6f\xb8\ +\x4b\x2c\xc9\x9b\x40\xc8\x98\x19\xec\x0f\x6f\x4a\x28\x29\xfe\x0b\ +\xd2\x85\xb9\x24\x75\x07\xf7\xb0\xbe\xb3\x91\x95\xf8\x71\x95\x25\ +\xb5\x47\x12\xb2\x89\x36\xc3\x63\x41\xb6\xf5\x8d\x00\x1f\x5f\x12\ +\xe2\xdd\x3c\x47\xf1\x24\x23\x04\xa6\xa4\x55\xe8\xe4\x39\x3f\xcb\ +\x80\x1c\xdc\x03\x92\x80\x84\x77\xfc\x0d\x3f\x04\xfe\x83\x07\xfd\ +\x8b\xb3\xf6\x4a\x28\x74\xaa\x0b\xfc\x2d\x2b\x0d\x29\x79\x64\x81\ +\xff\x26\x19\x6e\x4e\xae\x13\xd0\x05\x93\x6a\xcc\x50\x89\xb1\xf0\ +\xa7\x83\xbb\x57\x12\x90\xf0\xa0\xa5\xfe\xbd\xfe\x16\xe8\xef\xeb\ +\xfb\x67\xee\x18\xb1\xa8\xdc\xef\xa6\x9d\x7b\xe4\xba\x20\x27\xd8\ +\x86\x2b\x01\xe1\x4b\x6d\xfd\x8c\xd4\x60\x56\x88\x55\x70\x4d\x85\ +\xfc\x9f\xd1\x56\x2f\xcf\x4e\x60\x13\x1f\x5f\x1f\x81\x90\x85\x16\ +\xe2\x6d\xf4\x8c\x73\x20\x66\xb1\xae\x9b\x5f\xca\xe9\x81\x96\x12\ +\x92\x03\xe3\x0a\xbc\x8f\xa9\xf1\x83\x76\x45\xa8\x36\x07\x69\x34\ +\x38\x67\xb0\x3d\xaa\x88\xec\xc4\xf7\x3d\x9e\xaa\x67\x31\x8a\x4f\ +\xc0\x8a\x40\x61\xce\xaa\x7a\x3f\x64\xfe\xfc\xae\xc2\x98\x97\x21\ +\x26\x2c\x89\x49\x08\x98\x3f\x97\x7d\x7b\xa8\x49\xb3\xad\x27\xd3\ +\xe0\xf7\x47\x3b\x56\x7b\x86\xb4\x94\x42\xd6\xa3\x06\x02\xa6\x8c\ +\x29\xb9\xd7\x02\x78\x7c\xee\xf8\xe8\x42\x42\xe2\xea\x5d\x58\x30\ +\x7b\xb1\xcf\x7b\x62\x22\x60\xf6\xd2\xde\x7e\x19\x1e\x6a\x40\x5d\ +\xdb\xa6\x39\xcb\x25\xdc\x1d\x4f\x57\xe3\x7c\x7b\xec\xe6\x94\xe5\ +\xbe\xee\xc5\x8a\x68\xeb\xfd\xf9\x81\xef\x27\x9b\x83\xc3\xb6\x06\ +\x85\x79\xcf\xd6\x6e\x62\xb3\xa4\xce\x95\x50\xe6\xa4\x84\xcd\x32\ +\x29\x24\x26\xd0\xd1\xe5\xfb\xe9\x0c\x5f\x42\xf1\xf1\xb7\x3a\x45\ +\xf1\xfe\x81\x22\xe2\xc3\x6b\xb7\xaa\xaa\x71\x9f\x95\x32\xc1\x9c\ +\xba\xb6\x4d\x13\x96\x4b\xcc\x12\x8f\x54\x21\x6d\x94\x66\xbe\xb7\ +\xb6\x3b\x6d\xb9\x0a\x1e\x29\x5e\x9d\x34\x75\xbc\xd7\xfa\x9d\xa8\ +\xb9\xef\xd9\xdc\x2c\xa8\x73\xc5\x27\xe5\x9d\x96\x02\x50\x6e\x74\ +\x2e\x2e\x3b\x4a\x4d\xab\x5d\x4b\x4b\x46\x50\xa7\xb6\xdc\xac\xdd\ +\xd5\xf0\x90\x30\x1b\xdc\xb2\x4f\xae\x45\xe5\xde\xfc\x7a\xcd\x91\ +\x66\x68\xfb\x2a\x0b\x2c\xb7\xea\xf6\x87\xcc\x24\x26\xe4\xdd\xe5\ +\x07\xb0\x13\xad\x15\x70\x35\x97\x85\xcc\xf1\xf1\xf0\xb9\xbb\x7c\ +\xdc\x8f\x8c\xf1\x8e\xa3\x95\xd6\x86\x47\xb7\x2b\x0b\xe0\x82\x4e\ +\xc4\x27\x61\x52\x67\x40\x97\xa4\xe4\x27\xef\xc5\x0e\x33\x83\xca\ +\x8a\x3a\x17\xc0\x67\x51\x1b\xed\xec\xf2\xfd\x86\x21\x8b\xe0\x5e\ +\xbe\x93\xdd\x68\x07\xe4\x96\x25\xc6\xa7\x20\xdf\x5f\xfb\xd5\x41\ +\x64\x3b\xda\x01\xc1\x25\xa7\x00\xa2\xe7\x54\xb2\xa6\x58\xec\x47\ +\x3b\x20\xb8\x95\xc5\x56\xce\x57\x62\x99\x53\x1c\xce\x8e\x38\xa5\ +\x5b\x40\x3b\x20\xb8\xdb\xd2\x19\x33\x09\x18\x0b\xcc\x2e\xed\xa6\ +\x88\xc7\xf8\x16\xd0\x0e\xba\x41\xa5\xb9\x8e\x98\x12\x5d\x36\xae\ +\x47\x3c\xe6\x3c\xde\x02\xda\x41\xc3\x05\xd0\x42\x27\xcc\x48\xcf\ +\x4d\x07\x15\x8f\x39\x93\x61\x86\x24\x2e\xd7\xc0\xe1\x02\x68\xce\ +\x88\xe4\x9c\x51\xf1\xb7\x85\xd6\x0a\xb8\xd5\xb8\xda\x48\x4e\xcc\ +\x38\x7e\x6b\x68\x2d\x81\x0b\xa0\x23\x3c\x49\x40\xbe\xb6\x3f\x4d\ +\xee\xf6\xd0\x0e\xb6\xb5\xbc\x57\x8f\xfc\x9b\xfc\x98\x3f\xe5\xeb\ +\x6f\xf3\x07\x6f\x11\xad\x45\x96\x0b\x5a\xf0\x2f\x7c\x95\x9f\x7f\ +\xfb\x89\x04\xa4\xb7\x87\xd6\x2a\xb8\xa0\x23\xfe\x1b\xf8\xdc\xf6\ +\xbb\x12\x90\x30\xba\x3d\xb4\x96\xc1\x05\xfe\x80\x4f\xb8\xdb\x7c\ +\xe3\xf2\x54\x55\x7b\x64\x19\x5c\x2d\xf9\x47\x3e\xfb\xfa\xfa\x96\ +\xd1\xda\xd5\xa0\x02\x40\xc7\x1b\xab\x09\xdc\x34\x5a\xeb\x2c\x17\ +\x5e\xf3\x09\x6f\x1d\xad\x95\x70\xd7\x3a\x84\x56\x4e\x06\x3b\xec\ +\x91\xa5\x70\x25\x22\xde\x8b\x36\xc3\xc7\x97\xac\xce\x31\x87\x27\ +\xeb\xea\x5c\x38\x9c\xaa\xba\x1e\x1a\x2d\x01\xad\xae\x5a\xdb\x1f\ +\x59\x08\xf7\x48\x16\x72\xcc\x3d\x98\x1b\xb9\xde\x77\x59\xe7\x96\ +\x0f\xa3\x95\xb0\xca\xe7\x08\x5b\x5c\xc9\xa7\x57\xb2\xcc\x72\x8f\ +\x8e\x1d\x08\x29\xc5\xc3\x27\xe2\xbe\xeb\x72\x5e\x47\x56\xc1\x3d\ +\x31\x2c\x24\x60\x41\x02\xdc\x19\x5b\xd8\xb8\xe7\xb2\x08\xee\xc9\ +\x11\x3f\x21\x77\xb7\x15\x61\xb6\x06\xae\x24\x70\x0c\xed\x7a\xb5\ +\xcc\xae\x4b\x79\x5d\x59\x02\xf7\x8c\x54\xd5\x9c\xba\xe3\xf8\x06\ +\xfb\x97\xb0\x02\xee\x39\x59\xc8\x5a\xde\x4a\x1b\xf9\x55\x16\x74\ +\x85\x6e\x23\xc1\xbc\x8e\x06\x0f\xd7\xa1\x3d\xac\x81\xc3\x75\x68\ +\x8f\x69\xd0\x70\x1d\xda\xe3\x1a\x2c\x5c\xf1\x64\xce\xc2\x56\xb4\ +\x32\x97\xa5\xf8\xd2\x70\x09\xab\x81\xc2\x15\x8f\x39\x53\xd3\x53\ +\xfb\xf4\x48\x23\x3c\x2d\x28\x99\x36\x89\xa6\x0d\xb2\x2b\x64\x7f\ +\x16\xb2\x96\xf2\xb8\x9e\x3a\xbf\xc9\x51\x06\x68\xb9\x1d\xa0\xed\ +\x62\xf1\xe4\x69\xf3\xbb\xce\x83\x83\xdb\x89\xd5\x76\x30\x9b\x8d\ +\x96\x2c\x9a\x86\x5d\x06\x06\xd7\x7e\x87\xbc\xa1\xa2\xe9\xdd\xab\ +\x41\xd5\xb9\xb7\x83\x56\x62\x68\x3e\x63\xfa\x80\xe0\x4a\xc0\x98\ +\xd1\x8d\xdc\x8b\x2d\x4d\x4c\xf3\x39\x18\xb8\xb7\x95\x85\x6c\xa6\ +\x93\x37\x90\x3a\xf7\xb6\xd0\x9a\xd2\x20\xe0\x3a\xb4\xf5\x34\x00\ +\xb8\x0e\x6d\x5d\xf5\x1f\xee\xcf\x39\xb4\x75\xd5\x77\xb8\xbf\xc1\ +\x2f\x3a\xb4\x75\xd5\x77\xb8\xbf\xca\x07\x0e\x6d\x5d\xf5\xbd\x2b\ +\xf4\x13\x7e\x49\xfe\x95\x4f\x3a\x39\xf7\xc1\x70\x49\x77\x03\xc9\ +\xf4\xa2\x74\xfa\x5e\xc3\x95\x80\x2f\xf2\x5f\xfc\x2e\x7f\xcb\xf7\ +\x3a\x38\xfd\x73\xb8\xe4\xa7\x6f\x3e\x69\x74\xaf\xe6\xa8\x7e\x9d\ +\x1f\x19\x3c\x5a\xd7\x2b\x07\x1d\x59\x71\x27\xe0\x89\x58\x21\xe6\ +\xa9\xfe\x6a\x41\x06\xca\x91\x90\x5c\xe9\x4c\x31\x4f\x9b\xab\x08\ +\x36\xdd\x7a\x5b\xe7\x4a\x40\xc6\x44\x67\xa0\x33\xee\x89\x64\x7e\ +\xc9\xf4\x9d\x03\x55\xc8\xbd\xc9\x16\x46\x4f\xe1\xbe\xa2\x05\xd0\ +\x9c\x7b\x4a\x32\x73\xab\xb9\xf7\x4f\x12\x83\x3e\x98\xbd\x29\xd2\ +\x4b\xb8\xdb\x68\x01\xb4\xd4\x11\x33\xe6\x76\x4e\x79\x20\x9e\xa4\ +\xb4\x70\x65\x3d\x84\xfb\x16\xed\x5a\x3a\xe3\x81\xf1\x65\xb3\x2b\ +\x0f\x46\x65\x1b\xc3\x4a\x7b\x07\x57\xfc\xfd\x68\x01\x34\xe7\x0e\ +\xcf\x2e\xf7\x2c\x9e\xa4\x5a\x6a\xad\x35\x91\x4e\xa9\x67\x70\xab\ +\xdb\xf1\x07\x13\x56\xb5\xd4\x07\x1e\xc9\x6c\x71\xcf\xe2\xd3\x62\ +\x9f\xb9\x57\xfd\x5c\xf1\xc8\x4e\xe7\x22\xeb\x54\x16\xcc\xc5\x8a\ +\xd5\xf7\xb4\x90\x89\xd6\x58\x11\xe9\x3c\xf5\xc8\x72\xc5\x23\x23\ +\xd7\x33\x16\x07\x5e\xbb\xe7\x66\x09\xdb\xdd\x4b\x02\xc9\xa0\x3d\ +\xb4\x3d\x82\x5b\xa1\x3d\xd3\x1a\x2b\xf7\xbc\x94\xa8\xeb\x72\xd7\ +\xbe\x5e\x9f\x8c\x96\xc7\x4b\xf4\xc4\x2d\x5f\x86\x76\x2d\x9d\x4a\ +\xce\x5c\x82\x73\x6c\xbd\x6f\x12\x4f\x0b\x79\xd7\xf6\x2d\x91\x5e\ +\x58\x6e\x1d\xb4\x00\xba\xe0\x1d\x0d\xc7\xd3\x74\x72\xbd\x63\x96\ +\xdb\x6b\x5e\xb7\xa3\x1e\xc0\xad\x8b\x16\xaa\xa5\x2b\x16\xc3\x72\ +\xcf\x12\x10\x6d\xcf\x09\xdd\x96\x3a\x77\xcb\x4d\xd0\xae\xa5\x93\ +\xaa\xf5\x3c\x08\xf7\x2c\x81\xe6\xd7\x41\xdb\x07\xcb\x9d\x37\x43\ +\x0b\x2f\xee\x39\xeb\x7b\xec\x4a\x3c\xc9\xae\x39\xef\x64\xc7\x70\ +\x25\xa5\x30\xd1\x5f\xd5\x52\xef\xc9\x59\x9d\xb3\x74\xd4\xc5\x32\ +\xd7\x59\xf1\xc8\xf5\xa1\x85\x12\x1e\x52\xa7\x77\x6c\x53\x96\x46\ +\x8f\x17\xf1\x64\xfe\xde\x2b\xa1\x89\x63\xe2\x13\x5d\xfb\xf7\xed\ +\xd0\x72\x25\x25\x30\x11\x2e\x97\xf0\xb9\xb5\xac\x8f\xdc\x11\xf6\ +\xd1\x3d\x4b\xc0\xf2\xfa\x63\x05\x3b\x83\xbb\x46\xdb\xac\x3b\x20\ +\xbe\xfc\x93\x7c\xc8\xd7\x5f\xc7\x0f\x69\xa1\x77\xe4\xac\x7a\x77\ +\x6b\xa1\x64\xd4\xc1\x14\x0f\xdd\x39\xe4\x66\x09\x25\x7c\x91\xff\ +\xe4\x23\x94\x8f\xdf\x1e\x87\xc8\x64\x62\x4e\x53\xb7\x4c\x74\xad\ +\x34\x9d\x37\x67\xee\x03\x5a\xa2\xcb\x40\x93\xf0\xd3\xea\xe9\x87\ +\xfc\xc9\xde\x6f\xf8\x2c\x99\x9b\xc9\x47\x6a\x06\x97\x88\x27\x82\ +\x6e\xe0\x76\xe0\x96\xf7\x38\x64\x9f\x4c\x52\x89\x4f\x47\x9a\xc4\ +\x93\x50\x12\x7c\xfe\x9d\xbf\xe6\x47\xc0\x37\xf4\xfd\xbd\xfe\xa8\ +\xe0\x9e\x92\x65\x0f\xdc\xf3\xa2\xbb\xb9\x62\x45\xaf\x7d\xc2\x03\ +\x75\xad\x04\xac\xb7\x82\x62\xab\xf3\x51\x6a\x2e\x7e\xf5\x19\x94\ +\x14\x2c\xc8\xb5\x04\xf9\x01\x1f\xeb\xef\x1c\x3d\x57\x4c\xc2\xb4\ +\xd9\xa4\x21\x20\x21\x61\xbd\x00\x89\xa4\x94\x5d\x86\x56\xae\x0c\ +\x57\x92\x53\x19\x7e\xe2\x11\xbe\x99\x60\xc4\x7f\x45\xba\xf1\xcd\ +\x0f\xf8\xcd\x53\x0d\x32\x09\x48\x29\x18\x35\x69\xb8\xd5\x85\x2b\ +\x31\xb1\xd9\x6c\xc6\x8b\x75\xd5\xba\x36\x6e\xda\x8c\xda\x3a\xda\ +\x59\x35\x19\x1e\x29\xcb\x26\xb5\x1e\x21\xf3\x8b\xf7\xf1\xf0\x14\ +\x93\x39\xc8\xb5\x4a\x7e\x55\xb4\x4f\xf8\x9d\x5c\x64\xcc\x8a\xb8\ +\x01\xdc\xec\x62\xb4\xcb\xae\x5a\xc8\x9d\xc0\x25\xee\xae\xd5\xa8\ +\x10\xb0\x22\xad\x67\x49\x35\xe0\x8e\x49\xbb\x06\x7b\x45\xb8\xcd\ +\xd0\x12\x34\xb7\x78\x3c\xe6\xf5\xdc\xf3\x65\x70\x09\xba\xfb\x0b\ +\xef\x6e\x57\xe9\x0a\x49\x4c\xc2\x7d\xdd\x0e\x81\xcc\x89\x98\x37\ +\xbd\x21\x7f\x9d\xbc\x49\x09\xc8\x7a\xb4\x28\x55\xef\xad\x36\x21\ +\x55\x48\xcc\x44\x9c\xd6\xee\xb9\x3d\xcb\x25\xae\x5f\xb7\xb7\xf0\ +\xcb\xf7\x1c\xad\x8f\xe2\x2b\xcc\x4d\x35\x50\x2a\xf7\x7c\x81\x9b\ +\x3f\x17\x2e\x51\x7f\x1c\xf2\x7a\x6b\xd9\x2d\x37\x73\xc8\x40\x4c\ +\xae\x05\x06\xd7\xdf\x6b\x2b\x6f\x52\x62\x52\xb3\x47\x34\x71\xb1\ +\x6d\x5a\x6d\xd0\xb4\x85\xcc\x92\x15\x19\x19\x4a\x68\xb4\x64\xe1\ +\xf9\x77\x7e\xcf\xb3\x5c\xc2\xbe\xd9\x6d\xab\x6e\x99\x80\x55\xd3\ +\x0b\x5e\x43\x25\xe6\xc9\x78\xe9\x3c\xb2\xf3\xdc\xf3\x69\xb8\x24\ +\xd7\xbf\x11\x7f\xce\xd6\x9a\x5b\x96\x80\x8c\xa9\x81\x90\x79\x4b\ +\xeb\x66\x9a\xcb\x9b\x94\x84\xd0\x60\x2a\x8e\xd1\x8b\x6c\xcb\x6a\ +\x9f\x4c\xb4\x1b\xd1\xea\x58\x2d\x05\xf2\xce\x71\xcf\xa7\x2c\x17\ +\xbf\xeb\x30\xe3\xe1\x5f\xaf\xc7\x68\x15\x52\x62\x32\xb3\xf5\xed\ +\xce\x19\x3c\x32\xb2\x63\x78\x0e\xc3\xc5\x63\xd9\x66\xd9\x7a\x08\ +\xd7\x1c\x5a\x05\x8f\xb0\xfd\x78\x34\x09\x4f\x87\x21\x1d\x81\x9b\ +\xf6\x23\xcc\x78\x35\xb8\x26\xd1\x5e\xf1\x67\x38\x92\x37\xb9\x1f\ +\x6e\x37\xb7\x40\x2e\xdb\x0c\x37\xa8\x0e\x4d\x79\xd0\x77\x5d\x9a\ +\x37\x29\x41\x2f\xb2\x3c\x4e\xc8\x28\xdc\xa1\xa2\x85\x8b\xf3\x26\ +\xe3\x41\x4c\xc7\x6f\xd0\xb5\x79\x4d\xee\x9a\xf6\x63\xdb\x97\x37\ +\xb9\xeb\x96\x2f\x4d\xe7\xb3\xc0\x2d\x8b\x47\xc6\x6c\x98\x56\xfb\ +\x2a\x7d\xe4\xee\xf8\x84\x66\x12\x93\x76\xb1\x14\x4d\x1d\x19\x82\ +\x5b\x8d\xd5\x6b\x6f\x4e\xc4\xab\xe9\x64\xde\xa4\xcf\xfd\x60\x16\ +\xd1\x30\xe4\x90\x97\xfd\xee\x14\x5c\x7c\x45\x1b\xf3\x4d\xbe\xba\ +\x65\x92\xa1\x38\xe4\x33\xdd\xb2\xa4\xa2\xe2\x4b\x26\x07\x87\x1e\ +\x36\x1f\x61\xdb\x3f\xed\x9b\x6f\x52\xe6\xb4\x31\x86\xb0\xd5\xcb\ +\x38\xfd\x2f\x4e\x49\x8e\x74\xf1\xad\xb3\xda\x8d\x2b\x4b\x59\x12\ +\x3c\x5b\x6e\x9f\x63\x51\xfb\xb7\x33\xf2\x96\xc5\x67\x79\xe8\x9e\ +\xac\x8d\x56\xbb\x75\x7d\x31\x11\xdf\xe5\xf3\x7c\x32\xc8\xe5\xaa\ +\xce\xf8\x07\x8f\x09\xf6\xe7\x1b\xe3\xb1\xe4\xdb\x64\x24\x0a\x31\ +\x19\x99\x42\xb0\xf9\x48\xa0\x6c\x3d\xc6\x0a\x49\xf5\x18\x6f\xec\ +\x99\xec\xee\xa9\x1c\xd9\x33\xd9\xd9\x33\x3e\xba\x67\xb0\x75\xce\ +\x84\x70\x3d\xfe\x87\xb8\x7a\x4c\x14\xfc\xcd\x47\xfc\xf5\x2c\xcb\ +\xf8\x0a\x5f\xa3\xe4\xc3\x3e\x24\xaa\xb6\x60\xb9\x92\x52\xe8\x54\ +\x56\xe4\x4c\xb6\xff\xbb\x6b\xab\x65\x8a\x5f\x0d\xf9\xf0\x41\x17\ +\xe2\x11\xbc\x3e\x92\x6b\x29\xe1\xc6\x63\xa1\x85\x04\x78\x14\x5a\ +\x88\xbf\xb1\x67\xa9\xf9\xf6\x9e\xba\x80\x83\x7b\x06\x78\x5b\x7b\ +\xee\x9c\x7b\x67\xcf\x5c\xcb\xad\x3d\x77\xcf\x7d\xaa\xd4\x9f\xe1\ +\x8f\xf4\x4b\x5d\x1b\x61\x1d\x35\x18\x4e\x22\x29\xd8\xeb\x90\x6d\ +\x50\xed\xd9\x6c\x24\xc5\xbb\xea\xfc\x0e\x4e\x17\xab\x26\x5c\x53\ +\x53\x1e\x38\xb5\xa9\x5a\x11\x2a\x13\x53\x1e\x38\xb5\xaf\x1a\x70\ +\x1d\xda\xa1\xe8\x62\xb8\x0e\xed\x70\x74\x21\x5c\x87\x76\x48\xba\ +\x08\xae\x43\x3b\x2c\x5d\x00\x57\x12\x87\x76\x58\x3a\x1b\xae\xc4\ +\xa6\xd7\xab\x72\x6a\x5b\x67\xf6\x73\x25\x26\xa1\xf5\x99\xbd\x9d\ +\xcc\xea\x2c\xcb\xad\xc6\xea\x39\xb4\x03\xd3\x19\x70\x1b\x0f\xc3\ +\x74\xea\x48\xa7\x33\x31\x1c\xda\xc1\xea\x04\x5c\x87\x76\xc8\x3a\ +\x0a\xd7\xa1\x1d\xb6\x8e\xc0\x75\x68\x87\xae\x83\x37\xeb\x25\x22\ +\x75\x68\x87\xad\x03\x70\x25\x60\x8e\xe1\x75\x98\x9d\xae\xad\xbd\ +\x41\x0c\x09\xc8\x1c\xda\xe1\x6b\x0f\xdc\x6a\xac\x5e\x3f\x67\x79\ +\x70\x3a\x2a\xf9\x01\xdf\xaf\x9e\xfe\x36\xdf\x7c\x03\x77\xc8\xc3\ +\x30\x9d\x78\xe2\x79\xbc\xd6\x94\xc7\x1d\xb8\x0e\xed\xc0\xf5\xf4\ +\xec\x71\xe5\x49\xf3\xad\xae\x90\x43\x6b\x97\x36\xe0\x3a\xb4\xb6\ +\xe9\x05\xae\x43\x6b\x9f\x2a\xb8\xe2\x39\xb4\xf6\xe9\x3d\x70\x68\ +\x6d\xd5\x7b\x15\xda\x85\x43\x6b\x9f\x44\x11\x8f\xd8\x86\xd9\x2c\ +\x9c\x40\xbe\xc3\xff\x56\x4f\x7f\x99\x6f\x5d\x7d\x45\x30\xa7\x36\ +\xb5\xb5\x38\x74\xf9\xff\x29\xbd\xa0\x62\xdc\x46\x93\x65\x00\x00\ +\x00\x27\x74\x45\x58\x74\x63\x6f\x6d\x6d\x65\x6e\x74\x00\x43\x6f\ +\x70\x79\x72\x69\x67\x68\x74\x20\x32\x30\x31\x38\x20\x62\x79\x20\ +\x42\x72\x75\x63\x65\x20\x49\x6b\x65\x6e\x61\x67\x61\xf2\x53\x3c\ +\xf1\x00\x00\x00\x25\x74\x45\x58\x74\x64\x61\x74\x65\x3a\x63\x72\ +\x65\x61\x74\x65\x00\x32\x30\x31\x38\x2d\x30\x34\x2d\x30\x38\x54\ +\x32\x30\x3a\x32\x30\x3a\x30\x37\x2d\x30\x34\x3a\x30\x30\x7c\xdf\ +\xdc\xca\x00\x00\x00\x25\x74\x45\x58\x74\x64\x61\x74\x65\x3a\x6d\ +\x6f\x64\x69\x66\x79\x00\x32\x30\x31\x38\x2d\x30\x34\x2d\x30\x38\ +\x54\x32\x30\x3a\x32\x30\x3a\x30\x37\x2d\x30\x34\x3a\x30\x30\x0d\ +\x82\x64\x76\x00\x00\x00\x23\x74\x45\x58\x74\x70\x73\x3a\x48\x69\ +\x52\x65\x73\x42\x6f\x75\x6e\x64\x69\x6e\x67\x42\x6f\x78\x00\x31\ +\x35\x36\x78\x31\x34\x36\x2b\x32\x32\x38\x2b\x35\x36\x34\x3d\xd6\ +\x89\xef\x00\x00\x00\x1c\x74\x45\x58\x74\x70\x73\x3a\x4c\x65\x76\ +\x65\x6c\x00\x41\x64\x6f\x62\x65\x2d\x32\x2e\x30\x20\x45\x50\x53\ +\x46\x2d\x32\x2e\x30\x0a\xfe\x5a\x05\x03\x00\x00\x00\x00\x49\x45\ +\x4e\x44\xae\x42\x60\x82\ +" + +qt_resource_name = b"\ +\x00\x0b\ +\x0a\x50\x47\xc3\ +\x00\x63\ +\x00\x6f\x00\x6f\x00\x72\x00\x64\x00\x69\x00\x6e\x00\x61\x00\x74\x00\x65\x00\x73\ +\x00\x0c\ +\x09\x2f\x8f\x87\ +\x00\x73\ +\x00\x70\x00\x68\x00\x65\x00\x72\x00\x43\x00\x6f\x00\x6f\x00\x2e\x00\x70\x00\x6e\x00\x67\ +" + +qt_resource_struct_v1 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +" + +qt_resource_struct_v2 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01\x68\xdb\xce\xdd\x05\ +" + +qt_version = QtCore.qVersion().split('.') +if qt_version < ['5', '8', '0']: + rcc_version = 1 + qt_resource_struct = qt_resource_struct_v1 +else: + rcc_version = 2 + qt_resource_struct = qt_resource_struct_v2 + +def qInitResources(): + QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/Files/newCoilGUI.ui b/Files/newCoilGUI.ui new file mode 100644 index 0000000..c7ab8bd --- /dev/null +++ b/Files/newCoilGUI.ui @@ -0,0 +1,784 @@ + + + MainWindow + + + + 0 + 0 + 875 + 506 + + + + MainWindow + + + + + + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + B-Field (Gauss) + + + + + + + + 0 + 0 + + + + 100 + + + 1 + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Frequency (Hz) + + + + + + + + 0 + 0 + + + + 1 + + + 100.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 + + + + + + + + + + 0 + 0 + + + + Start + + + + + + + + 0 + 0 + + + + Stop + + + + + + + + 0 + 0 + + + + + 50 + false + false + false + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + false + + + 8 + + + QLCDNumber::Outline + + + + + + + + 0 + 0 + + + + Save Logfile and Close + + + + + + + + + + 0 + 0 + + + + QTabWidget::North + + + QTabWidget::Rounded + + + 3 + + + Qt::ElideLeft + + + false + + + + Fixed direction + + + + + + + + Fixed direction + + + + + + + 75 + true + + + + X + + + true + + + + + + + + 75 + true + + + + Y + + + + + + + + 75 + true + + + + Z + + + + + + + Negative Direction + + + + + + + + + + Field mode + + + + + + + 16777215 + 25 + + + + + 75 + true + + + + constant field + + + true + + + + + + + + 75 + true + + + + rotating field + + + + + + + + + + + + + Free direction + + + + + + + 0 + 0 + + + + Free direction + + + + + + + + + + + 0 + 0 + + + + + Symbol + 12 + 75 + true + + + + q + + + + + + + + 0 + 0 + + + + 180 + + + + + + + + + + + + 0 + 0 + + + + + Symbol + 12 + 75 + true + + + + f + + + + + + + + 0 + 0 + + + + 360 + + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + only constant fields ! Frequency has no effect + + + + + + + + + + + + + Continuous Script + + + + + + + + + 75 + true + + + + Number of points on unit sphere + + + Qt::PlainText + + + + + + + 10 + + + 10000 + + + 10 + + + + + + + + + <html><head/><body><p><span style=" font-weight:600;">Script for &quot;Random/Brownian Motion&quot;</span></p><p>Set the number of points being randomly <br/>distributed on a sphere with radius B. <br/>Sampling rate is specified by the frequency from below.</p></body></html> + + + + + + + + Dwell Script + + + + + + + + + 75 + true + + + + Number of points on unit sphere + + + Qt::PlainText + + + + + + + 10 + + + 10000 + + + 10 + + + + + + + + 75 + true + + + + Dwell time + + + Qt::PlainText + + + + + + + 0.100000000000000 + + + 500.000000000000000 + + + 0.100000000000000 + + + 3.000000000000000 + + + + + + + + 75 + true + + + + Move time + + + Qt::PlainText + + + + + + + 0.010000000000000 + + + 500.000000000000000 + + + 0.100000000000000 + + + 0.500000000000000 + + + + + + + + + + + 0 + + + + + + + Script length with current parameters (s) + + + + + + + + + + + Rotation in XY + + + + + + + true + + + Sphere script + + + true + + + + + + + + + + + + + + + + + + 0 + 0 + + + + true + + + Status + + + + + + + + 0 + 0 + + + + + 200 + 200 + + + + + Arial + 14 + 75 + true + + + + QFrame::StyledPanel + + + + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + Coil status + + + + + + + + 0 + 0 + + + + + + + + + + + + + 0 + 0 + 875 + 21 + + + + + File + + + + + + Properties + + + + + + + Spherical Coordinates + + + + + + + + + + + Choose calibration + + + + + Save Log & Close + + + + + Set new calibration + + + + + Definition + + + + + + + + + btn_start + released() + label_status + update() + + + 81 + 328 + + + 331 + 270 + + + + + diff --git a/Files/old_CoilGUI.py b/Files/old_CoilGUI.py new file mode 100644 index 0000000..c17cf51 --- /dev/null +++ b/Files/old_CoilGUI.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'CoilGUI.ui' +# +# Created: Mon Dec 05 17:13:53 2016 +# by: PyQt4 UI code generator 4.11.3 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName(_fromUtf8("MainWindow")) + MainWindow.resize(672, 472) + self.centralwidget = QtGui.QWidget(MainWindow) + self.centralwidget.setObjectName(_fromUtf8("centralwidget")) + self.gridLayout_4 = QtGui.QGridLayout(self.centralwidget) + self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4")) + self.gridLayout_7 = QtGui.QGridLayout() + self.gridLayout_7.setObjectName(_fromUtf8("gridLayout_7")) + self.groupBox_2 = QtGui.QGroupBox(self.centralwidget) + self.groupBox_2.setObjectName(_fromUtf8("groupBox_2")) + self.gridLayout_6 = QtGui.QGridLayout(self.groupBox_2) + self.gridLayout_6.setObjectName(_fromUtf8("gridLayout_6")) + self.verticalLayout_2 = QtGui.QVBoxLayout() + self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2")) + self.const_field = QtGui.QRadioButton(self.groupBox_2) + self.const_field.setChecked(True) + self.const_field.setObjectName(_fromUtf8("const_field")) + self.verticalLayout_2.addWidget(self.const_field) + self.rot_field = QtGui.QRadioButton(self.groupBox_2) + self.rot_field.setObjectName(_fromUtf8("rot_field")) + self.verticalLayout_2.addWidget(self.rot_field) + self.gridLayout_6.addLayout(self.verticalLayout_2, 0, 0, 1, 1) + self.gridLayout_7.addWidget(self.groupBox_2, 0, 0, 1, 1) + self.groupBox = QtGui.QGroupBox(self.centralwidget) + self.groupBox.setObjectName(_fromUtf8("groupBox")) + self.gridLayout_5 = QtGui.QGridLayout(self.groupBox) + self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5")) + self.verticalLayout = QtGui.QVBoxLayout() + self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) + self.x_dir = QtGui.QRadioButton(self.groupBox) + self.x_dir.setChecked(True) + self.x_dir.setObjectName(_fromUtf8("x_dir")) + self.verticalLayout.addWidget(self.x_dir) + self.y_dir = QtGui.QRadioButton(self.groupBox) + self.y_dir.setObjectName(_fromUtf8("y_dir")) + self.verticalLayout.addWidget(self.y_dir) + self.z_dir = QtGui.QRadioButton(self.groupBox) + self.z_dir.setObjectName(_fromUtf8("z_dir")) + self.verticalLayout.addWidget(self.z_dir) + self.neg_dir = QtGui.QCheckBox(self.groupBox) + self.neg_dir.setObjectName(_fromUtf8("neg_dir")) + self.verticalLayout.addWidget(self.neg_dir) + self.gridLayout_5.addLayout(self.verticalLayout, 0, 0, 1, 1) + self.gridLayout_7.addWidget(self.groupBox, 0, 1, 1, 1) + self.gridLayout_4.addLayout(self.gridLayout_7, 0, 0, 1, 1) + self.gridLayout_2 = QtGui.QGridLayout() + self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) + self.gridLayout = QtGui.QGridLayout() + self.gridLayout.setObjectName(_fromUtf8("gridLayout")) + self.label = QtGui.QLabel(self.centralwidget) + self.label.setObjectName(_fromUtf8("label")) + self.gridLayout.addWidget(self.label, 0, 0, 1, 1) + self.box_bfield = QtGui.QSpinBox(self.centralwidget) + self.box_bfield.setMaximum(360) + self.box_bfield.setObjectName(_fromUtf8("box_bfield")) + self.gridLayout.addWidget(self.box_bfield, 0, 1, 1, 1) + self.label_2 = QtGui.QLabel(self.centralwidget) + self.label_2.setObjectName(_fromUtf8("label_2")) + self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) + self.box_freq = QtGui.QSpinBox(self.centralwidget) + self.box_freq.setMaximum(360) + self.box_freq.setObjectName(_fromUtf8("box_freq")) + self.gridLayout.addWidget(self.box_freq, 1, 1, 1, 1) + self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1) + self.gridLayout_3 = QtGui.QGridLayout() + self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3")) + self.btn_stop = QtGui.QPushButton(self.centralwidget) + self.btn_stop.setObjectName(_fromUtf8("btn_stop")) + self.gridLayout_3.addWidget(self.btn_stop, 1, 0, 1, 1) + self.btn_start = QtGui.QPushButton(self.centralwidget) + self.btn_start.setObjectName(_fromUtf8("btn_start")) + self.gridLayout_3.addWidget(self.btn_start, 0, 0, 1, 1) + self.gridLayout_2.addLayout(self.gridLayout_3, 1, 0, 1, 1) + self.gridLayout_4.addLayout(self.gridLayout_2, 0, 1, 1, 1) + self.gridLayout_11 = QtGui.QGridLayout() + self.gridLayout_11.setObjectName(_fromUtf8("gridLayout_11")) + self.label_status = QtGui.QLabel(self.centralwidget) + self.label_status.setAutoFillBackground(True) + self.label_status.setObjectName(_fromUtf8("label_status")) + self.gridLayout_11.addWidget(self.label_status, 1, 0, 1, 1) + self.text_status = QtGui.QTextBrowser(self.centralwidget) + self.text_status.setObjectName(_fromUtf8("text_status")) + self.gridLayout_11.addWidget(self.text_status, 2, 0, 1, 1) + self.gridLayout_4.addLayout(self.gridLayout_11, 1, 0, 1, 1) + self.splitter = QtGui.QSplitter(self.centralwidget) + self.splitter.setOrientation(QtCore.Qt.Vertical) + self.splitter.setObjectName(_fromUtf8("splitter")) + self.label_field = QtGui.QLabel(self.splitter) + font = QtGui.QFont() + font.setFamily(_fromUtf8("Arial")) + font.setPointSize(14) + font.setBold(True) + font.setWeight(75) + self.label_field.setFont(font) + self.label_field.setFrameShape(QtGui.QFrame.StyledPanel) + self.label_field.setText(_fromUtf8("")) + self.label_field.setAlignment(QtCore.Qt.AlignCenter) + self.label_field.setObjectName(_fromUtf8("label_field")) + self.gridLayout_4.addWidget(self.splitter, 1, 1, 1, 1) + self.btn_close = QtGui.QPushButton(self.centralwidget) + self.btn_close.setObjectName(_fromUtf8("btn_close")) + self.gridLayout_4.addWidget(self.btn_close, 2, 0, 1, 1) + self.lcd_time = QtGui.QLCDNumber(self.centralwidget) + font = QtGui.QFont() + font.setBold(False) + font.setItalic(False) + font.setWeight(50) + font.setStrikeOut(False) + self.lcd_time.setFont(font) + self.lcd_time.setFrameShape(QtGui.QFrame.StyledPanel) + self.lcd_time.setFrameShadow(QtGui.QFrame.Sunken) + self.lcd_time.setSmallDecimalPoint(False) + self.lcd_time.setNumDigits(8) + self.lcd_time.setSegmentStyle(QtGui.QLCDNumber.Outline) + self.lcd_time.setObjectName(_fromUtf8("lcd_time")) + self.gridLayout_4.addWidget(self.lcd_time, 2, 1, 1, 1) + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QtGui.QMenuBar(MainWindow) + self.menubar.setGeometry(QtCore.QRect(0, 0, 672, 21)) + self.menubar.setObjectName(_fromUtf8("menubar")) + self.menuFile = QtGui.QMenu(self.menubar) + self.menuFile.setObjectName(_fromUtf8("menuFile")) + self.menuCalibration = QtGui.QMenu(self.menubar) + self.menuCalibration.setObjectName(_fromUtf8("menuCalibration")) + MainWindow.setMenuBar(self.menubar) + self.statusbar = QtGui.QStatusBar(MainWindow) + self.statusbar.setObjectName(_fromUtf8("statusbar")) + MainWindow.setStatusBar(self.statusbar) + self.menu_calib = QtGui.QAction(MainWindow) + self.menu_calib.setObjectName(_fromUtf8("menu_calib")) + self.menu_close = QtGui.QAction(MainWindow) + self.menu_close.setObjectName(_fromUtf8("menu_close")) + self.manue_newcalib = QtGui.QAction(MainWindow) + self.manue_newcalib.setObjectName(_fromUtf8("manue_newcalib")) + self.menuFile.addAction(self.menu_close) + self.menuCalibration.addAction(self.menu_calib) + self.menuCalibration.addAction(self.manue_newcalib) + self.menubar.addAction(self.menuFile.menuAction()) + self.menubar.addAction(self.menuCalibration.menuAction()) + + self.retranslateUi(MainWindow) + QtCore.QObject.connect(self.btn_start, QtCore.SIGNAL(_fromUtf8("released()")), self.label_status.update) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) + self.groupBox_2.setTitle(_translate("MainWindow", "Signal", None)) + self.const_field.setText(_translate("MainWindow", "constant field", None)) + self.rot_field.setText(_translate("MainWindow", "rotating field", None)) + self.groupBox.setTitle(_translate("MainWindow", "Direction", None)) + self.x_dir.setText(_translate("MainWindow", "x", None)) + self.y_dir.setText(_translate("MainWindow", "y", None)) + self.z_dir.setText(_translate("MainWindow", "z", None)) + self.neg_dir.setText(_translate("MainWindow", "Negative Direction", None)) + self.label.setText(_translate("MainWindow", "B-Field (Gauss)", None)) + self.label_2.setText(_translate("MainWindow", "Frequency", None)) + self.btn_stop.setText(_translate("MainWindow", "Stop", None)) + self.btn_start.setText(_translate("MainWindow", "Start", None)) + self.label_status.setText(_translate("MainWindow", "Status", None)) + self.btn_close.setText(_translate("MainWindow", "Save Logfile and Close", None)) + self.menuFile.setTitle(_translate("MainWindow", "File", None)) + self.menuCalibration.setTitle(_translate("MainWindow", "Properties", None)) + self.menu_calib.setText(_translate("MainWindow", "Choose calibration", None)) + self.menu_close.setText(_translate("MainWindow", "Save Log and Close", None)) + self.manue_newcalib.setText(_translate("MainWindow", "Set new calibration", None)) + diff --git a/PyCoil.py b/PyCoil.py new file mode 100644 index 0000000..f5c4028 --- /dev/null +++ b/PyCoil.py @@ -0,0 +1,443 @@ +# -*- coding: utf-8 -*- +""" +Created on Wed Sep 07 10:08:09 2016 + +@author: sachs +""" + +from PyQt4 import QtGui, QtCore # Import the PyQt4 module we'll need +import sys # We need sys so that we can pass argv to QApplication +from time import strftime +import time +import os +import csv + +import Files.CoilGUI # This file holds our MainWindow and all design related things +#get it with QtDesigner - Save as .ui and then run +# 'pyuic4 design.ui -o design.py' in an console +# it also keeps events etc that we defined in Qt Designer +from Files.Caio_ctype import Caio #Import the low_level commands to the AnalogOutput Device +import Files.Function as signal #Import sinewave, constant, writebuffer, direction +import numpy as np + +#get start timestamp +#startprog = datetime.datetime.now() + +#initialize device +device = Caio() +# device.DaveiceName = 'AO-1604LX-USB' +# device.DeviceName == 'AIO001' + +#get current dir and create \Log folder +curDir = os.getcwd() +if not os.path.exists(curDir+'\Logs'): + os.mkdir('Logs') +os.chdir(curDir+'\Logs') + +#create Logfile +name_logfile = strftime("PyCoil_%Y%m%d__%H_%M_%S.txt") +text_file = open(name_logfile, 'w') + + +#Start the GUI +class PyCoilApp(QtGui.QMainWindow, Files.CoilGUI.Ui_MainWindow): + def __init__(self): + super(self.__class__, self).__init__() + self.setupUi(self) # This is defined in CoilGUI.py file automatically + + + self.btn_start.clicked.connect(self.startCoil) # Connect btn_start with the sartCoil function + self.btn_stop.clicked.connect(self.stopCoil) + self.btn_close.clicked.connect(self.closeEvent) + self.menu_close.triggered.connect(self.closeEvent) + self.menu_calib.triggered.connect(self.getCalibration) + self.manue_newcalib.triggered.connect(self.newCalibration) + self.actionShow_drawing.triggered.connect(self.sphDef) + + self.initUI() + +######### Never change anything outside this area + def initUI(self): + self.label_status.setText('Status for Session: ' + name_logfile) + + self.timer = QtCore.QTimer(self) + self.timer.timeout.connect(self.Time) + self.timer.start(1000) + self.lcd_time.display(strftime("%H:%M:%S")) + self.fixedDir.show() + self.fixedDir.isActiveWindow() + self.tabWidget.setCurrentIndex(0) + self.PhiBox.setValue(0) + self.ThetaBox.setValue(90) + self.box_bfield.setValue(1) + self.box_freq.setValue(1) + self.calc_scripttime.setText(str(self.npoints_Dwell.value()*(self.movetime.value()+self.dwelltime.value()))) + + + + + # check if device is connected + if device.Id == -1: # Id=0 if properly connected + QtGui.QMessageBox.information(self, 'Error: No Device found', 'No device (AO-1604LX-USB) found. Connect device properly and restart PyCoil') + #self.deleteLater() + text_file.close() + os.remove(name_logfile) + return + print '_FOUND ' + device.DeviceName + print '_KNOWN AS ' + device.Device + print ' status ' + str(device.status) +'\n DeviceType '+ str(device.DeviceType) +'\n Id '+ str(device.Id) +'\n repeat_times '+ str(device.repeat_times) + + string = '### New session' + '\n' + strftime("### %Y-%m-%d %H:%M:%S") + self.text_status.append(string) + text_file.write(string) + self.getCalibration() + + + def getCalibration(self): + #global curCalib + curCalib=[] + #os.listdir(curDir+'\calibration') + if not os.path.exists(curDir+'\calibration') or signal.list_f_ext(curDir+'\calibration', 'txt') == []: + QtGui.QMessageBox.information(self,'Error: No calibration file', + 'No calibration file found in '+ curDir + '\calibration' + '\n' + + 'Using Standard calibration instead') + curCalib = [0.01,0.01,0.01] + filename = 'Standard calibration' + + else: + #get available calibration files + items = signal.list_f_ext(curDir+'\calibration', 'txt') + #choose a file + filename, ok = QtGui.QInputDialog.getItem(self, 'Choose calibration', 'Choose one of the calibration files found in \n' + + curDir + '\calibration', + items, 0, False) + #open file and extract values + if ok: + #print(curDir + "\calibration\\" + filename) + try: + with open(curDir + "\calibration\\" + filename, mode='r') as f: + reader = csv.reader(f) + row1 = next(reader) + curCalib = [float(row1[0]), float(row1[1]), float(row1[2])] + print('current calibration:'+ str(curCalib)) + + except: + QtGui.QMessageBox.information(self,'Wrong input','Cannot read calibration file syntax\n'+ + 'Using standard calibration .01,.01,.01 instead!') + curCalib = [0.01, 0.01, 0.01] + filename = 'Standard calibration' + +# string= ('Set calibration to: '+str(curCalib)+' (from '+filename+')') +# self.text_status.append(string) +# text_file.write('\n' + string) + + else: + QtGui.QMessageBox.information(self,'Aborted','Loading calibration aborted!\n'+ + 'Using standard calibration .01,.01,.01 instead!') + curCalib = [0.01,0.01,0.01] + filename = 'Standard calibration' + + string= ('Set calibration to: '+str(curCalib)+' (from ' +filename+')') + self.curCalib=curCalib + self.text_status.append(string) + text_file.write('\n' + string) + + + + + def newCalibration(self): + + x, xok = QtGui.QInputDialog.getDouble(self, 'Calibration factor for X', + 'Calibration factor is the slope of B_real/B_teoretical \n \n Enter calibration value for X', value=self.curCalib[0], decimals = 5) + y, yok = QtGui.QInputDialog.getDouble(self, 'Calibration factor for Y', + 'Calibration factor is the slope of B_real/B_teoretical \n \n Enter calibration value for Y', value=self.curCalib[1],decimals = 5) + z, zok = QtGui.QInputDialog.getDouble(self, 'Calibration factor for Z', + 'Calibration factor is the slope of B_real/B_teoretical \n \n Enter calibration value for Z', value=self.curCalib[2],decimals = 5) + if xok and yok and zok: + curCalib = [x,y,z] + + if not os.path.exists(curDir+'\calibration'): + os.mkdir('calibration') + + os.chdir(curDir+'\calibration') + cf = open('Calib'+name_logfile,'w') + cal = str(x)+','+str(y)+','+str(z) + cf.write(cal) + cf.close() + + QtGui.QMessageBox.information(self,'Calibration successful','New calibration set: '+str(curCalib)+'\n'+ + 'Saved calibration data as ...\calibration\\'+cf.name) + + string= ('Set calibration to: '+str(curCalib)+' (from '+'Calib'+name_logfile+')') + self.text_status.append(string) + text_file.write('\n' + string) + + print('current calibration:' + str(curCalib)) + self.curCalib=curCalib + + else: + QtGui.QMessageBox.information(self,'Aborted','New calibration aborted! \n'+ + 'Please try again') + + def Time(self): + self.lcd_time.display(strftime("%H:%M:%S")) + self.calc_scripttime.setText(str(self.npoints_Dwell.value()*(self.movetime.value()+self.dwelltime.value()))) + + + def startCoil(self): + #time.sleep(0.5) + device.tozero() + #get B-field and freqeuncy + b_field = self.box_bfield.value() + freq = self.box_freq.value() + + #Set maximum values for B and f + if b_field>80: #General maximum for B + device.tozero() + self.label_field.setText('!-ERROR-!\n Too high field! \n max. B < 80G ! ') + return + + #check which signal is selected + # first sc check if free direction is selcted + if self.tabWidget.currentIndex() == 0: + print 'fixed direction' + if self.tabWidget.currentIndex() == 1: + print 'free direction' + #curCalib=[1, 1, 1] + theta = np.deg2rad(self.ThetaBox.value()) + phi = np.deg2rad(self.PhiBox.value()) + # spherical coordinates in x,y,z + spXarray = np.sin(theta) * np.cos(phi)*np.ones((5, 1)) + spYarray = np.sin(theta) * np.sin(phi)*np.ones((5, 1)) + spZarray = np.cos(theta) * np.ones((5, 1)) + spX = spXarray * self.curCalib[0] * b_field + spY = spYarray * self.curCalib[1] * b_field + spZ = spZarray * self.curCalib[2] * b_field + + buf = signal.writebuffer(spX.round(15), spY.round(15), spZ.round(15)) + device.n_channels = 3 # set number of channels to 3 + device.buffer = buf + device.start() + string = (strftime("%H:%M:%S -- ") + # add timestamp + 'constant B-field along (Theta, Phi) = (' + str(np.rad2deg(theta).round(2)) + ', ' + str(np.rad2deg(phi).round(2)) + + ') // (x,y,z) = (' + str(spXarray[0].round(5)) + ', ' +str(spYarray[0].round(5)) + ', ' + str(spZarray[0].round(5)) + + ') , Amplitude: ' + str(b_field) + + 'G // Frequency: ' + str(freq) + 'Hz') + + self.label_field.setText('constant field along \n(Theta, Phi) = (' + str(np.rad2deg(theta).round(2)) + ', ' + str(np.rad2deg(phi).round(2)) + + ') \n(x,y,z) = (' + str(spXarray[0].round(5)) + ', ' +str(spYarray[1].round(5)) + ', ' + str(spZarray[2].round(5)) + ')') + + # write status and new line to logfile + self.text_status.append(string) + text_file.write('\n' + string) + return + + # run script with random motion + if self.tabWidget.currentIndex() == 2: + #print device.fs + print 'run random motion Script' + + + sample_points = self.npoints.value() # number of points on sphere + + script_duration = sample_points/freq + step_duration = 1/freq + device.fs=10*freq # real sampling is 10 times target sampling rate + + pt_vec = signal.golden_spiral(int(sample_points)) #create a 'random' trajectory on sphere with evenly space step size + # Open Function.py to the trajectory + + # ____ OLD CODE ____ + # points = signal.traj_on_sphere(10)#create points on sphere with evenly distributed theta + # random_vec = signal.spherical_points(int(sample_points)) #create randomly distributed points on a sphere + # __________________ + # np.savetxt("C:/Temp/raw_N200.csv", pt_vec, delimiter=",") + + buf_array = np.repeat(pt_vec, device.fs*step_duration, axis=0) #create buffer array with the correct number of samples + buf_array = buf_array*self.curCalib*b_field #and correct output voltage + + TTL = np.zeros((buf_array.shape[0], 1)) #create TTL trigger column + TTL[0:int(device.fs*step_duration)] = 5 #set first value to 5 volts + randTTL = np.append(buf_array, TTL, axis=1) #append column with zeros for TTL trigger + + + buf_array = randTTL.round(15) #rename as buf_array again + #np.savetxt("C:\Users\sachs\Documents\Random_rawN" + str(sample_points) + ".txt", buf_array, delimiter=",") + device.n_channels = 4 #set 4 output channels + device.buffer = buf_array + device.start() + + string = (strftime("%H:%M:%S -- ") + # add timestamp + 'Artificial random motion script with Amplitude: ' + str(b_field) + + 'G // Frequency: ' + str(freq) + 'Hz // Dwell: ' + str(step_duration) +'s and the following points [x, y, z]:' + + ) + + self.label_field.setText('Running random motion script with\n' + str(freq) + 'Hz (Dwell= '+ str(step_duration)+ 's) and ' + str(b_field) + + 'G\n\nPattern is repeated after '+ str(script_duration) + ' seconds!') + + + self.text_status.append(string + ' .... (see .txt file for details)') + text_file.write('\n' + string + '\n' + np.array2string(buf_array, precision=5, separator=',', edgeitems=5000, suppress_small=True)) + #device.fs=initial_sampling + + return + + + # run script with fixed dwell time + if self.tabWidget.currentIndex() == 3: + #print device.fs + print 'run fixed dwell time Script' + + + sample_points = self.npoints_Dwell.value() # number of points on sphere + step_duration = self.movetime.value() + self.dwelltime.value() + + script_duration = sample_points * step_duration + device.fs=25*(1/float(step_duration)) # real sampling is 25 times target sampling rate + + if self.radBut_Dwell_XY.isChecked(): + modestring = '(circle)' + pt_vec = signal.circleXY(int(sample_points)) #create circular trajectory in XY + else: + modestring = '(sphere)' + pt_vec = signal.golden_spiral(int(sample_points)) #create a 'random' trajectory on sphere with evenly space step size + + buf_array = np.repeat(pt_vec, device.fs*step_duration, axis=0) #create buffer array with the correct number of samples + buf_array = buf_array*self.curCalib*b_field #and correct output voltage + + #create TTL pulse in 4th column + stepsondev = (int(device.fs * step_duration)) #number of points being sampled on device + TTL_perStep = np.zeros((stepsondev, 1)) #create TTL trigger column for one step + startidx = int(np.ceil(self.movetime.value() * device.fs)) #wait for movetime specified + endidx = startidx+stepsondev/2 #trigger pulse length is half of device sampling freq. + TTL_perStep[startidx:endidx] = 5 #set TTL high (5 volts) + TTL = np.tile(TTL_perStep.T, sample_points).T #create array with correct number of samples + + randTTL = np.append(buf_array, TTL, axis=1) #append column with zeros for TTL trigger + + buf_array = randTTL.round(15) #rename as buf_array again + + device.n_channels = 4 #set 4 output channels + device.buffer = buf_array + device.start() + + string = (strftime("%H:%M:%S -- ") + # add timestamp + 'Dwell time script ' + modestring + ' with ' + str(sample_points) +' points, Amplitude: ' + str(b_field) + + 'G // Frequency: ' + str('%.2f' %(1/step_duration)) + 'Hz // Dwell time: ' + str(self.dwelltime.value()) +'s and the following coordinates [x, y, z]:' + + ) + + self.label_field.setText('Running Dwell time script' + modestring + 'with\n' + str('%.2f' %(1/step_duration)) + 'Hz (Dwell= '+ str(self.dwelltime.value())+ 's) and ' + str(b_field) + + 'G\n\nPattern is repeated after '+ str(script_duration) + ' seconds!') + + + self.text_status.append(string + ' .... (see .txt file for details)') + text_file.write('\n' + string + '\n' + np.array2string(buf_array, precision=5, separator=',', edgeitems=5000, suppress_small=True)) + #device.fs=initial_sampling + + return + + + # otherwise use the fixed directions + if self.const_field.isChecked(): + coil_signal = 'constant' + text = ('Constant along ') + else: + coil_signal = 'rotate' + text = ('Rotation in ') + if not (0 < freq <= 40): # frequency range 0 to 40 + device.tozero() + self.label_field.setText('!-ERROR-!\n No frequency set or\n Frequency too high \n max f < 40Hz ! ') + return + + + #direction negative? + if self.neg_dir.isChecked(): + coil_dir = '-' + else: + coil_dir = '' + + + + #check which direction is selected and append + if self.x_dir.isChecked(): + coil_dir = coil_dir + 'x' + self.label_field.setText(text + (coil_dir.upper() if self.const_field.isChecked() else 'Y-Z plane (along ' +coil_dir+')')) + if self.y_dir.\ + isChecked(): + coil_dir = coil_dir + 'y' + self.label_field.setText(text + (coil_dir.upper() if self.const_field.isChecked() else 'X-Z plane (along ' +coil_dir+')')) + if self.z_dir.isChecked() == True: + coil_dir = coil_dir + 'z' + self.label_field.setText(text + (coil_dir.upper() if self.const_field.isChecked() else 'X-Y plane (along ' +coil_dir+')')) + + #set signal to zero ??? + #device.tozero() + + #write buffer and start output + device.fs=1000 + buf = signal.direction(coil_dir, coil_signal, b_field, freq, samp=1000, calibration=self.curCalib) #try different samples + device.n_channels = 3 # set number of channels to 3 + + device.buffer = buf + device.start() + + #status string + string = (strftime("%H:%M:%S -- ") + #add timestamp + self.label_field.text() + + ', Amplitude: ' + str(b_field) + + 'G // Frequency: ' + str(freq) + 'Hz') + + + #write status and new line to logfile + self.text_status.append(string) + text_file.write('\n' + string) + + #time.sleep(1) + #add matplotlib/picture of signals in x,y,z + + def stopCoil(self): + + string= (strftime("%H:%M:%S -- ") +'Field stopped') + self.text_status.append(string) + text_file.write('\n' + string) + + self.label_field.setText('---- Field stopped ----') + device.tozero() + + def sphDef(self): + QtGui.QMessageBox.information(self, "Definition used", "The used coordinates are choosen according to the ISO definition:\n\n" + " Theta -- inclination or polar angle between z-axis and xy-plane,\n Phi -- azimuthal angle in xy-plane, measured from x-axis\n\n" + " E.g. Theta=90, Phi=45 will lead to a vector in the xy-plane with coordiantes [0.7071, 0.7071, 0]") + + def closeEvent(self, event): + device.tozero() + #time.sleep(0.5) + device.stop() + device.reset_memory() + device.reset_status() + device.reset_device() + #time.sleep(0.1 ) + + path = os.getcwd() + + text_file.close() + + QtGui.QMessageBox.information(self, 'Saving Logfile...', 'Logfile saved as ' + + name_logfile + ' in' + '\n' + path + ) + self.deleteLater() + + +######### End of modification area + +def main(): + app = QtGui.QApplication(sys.argv) # A new instance of QApplication + form = PyCoilApp() # We set the form to be our PyCoilApp (design) + form.show() # Show the form + sys.exit(app.exec_()) # and execute the app + + +if __name__ == '__main__': # if we're running file directly and not importing it + main() # run the main function \ No newline at end of file diff --git a/README.md b/README.md index fe3f8e1..60c4bfd 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,10 @@ Code to drive a 3-axis Helmholtz coil with a GUI (based on a Contec AO-1604LX-US --- -This was one of my very first Pyton projects, so please don't slap me for some very complicated code structure. However, it grew over time and all it does is to drive an Analog Output device (Contec AO-1604LX-USB), which was connected to an amplifier and a custom 3-axis electromagnet. -The GUI was able to create a constant magnet field and time-varying fields in arbitrary directions. +This was one of my very first Python projects, so please don't slap me for some very complicated code structure. However, the project grew over time and has some nice features (which are obviously very specific to my needs). All it does is to drive an Analog Output device (Contec AO-1604LX-USB), which was connected to an amplifier and a custom 3-axis electromagnet. +The GUI is able to create a constant magnet field and time-varying fields (i.e. sine waves) in arbitrary directions. Any GUI action is automatically logged into a .txt file. This was quite helpful when the magnetic fields were synchronized with other equipments such as cameras. **Note: The low level communication with the AO device can be found in Caio_ctype.py and was written by somebody else: https://github.com/cboulay/caio_python + + \ No newline at end of file diff --git a/calibration/2nd_Cu_Coil_Calibration_15-Mar-19.txt b/calibration/2nd_Cu_Coil_Calibration_15-Mar-19.txt new file mode 100644 index 0000000..aa48bd4 --- /dev/null +++ b/calibration/2nd_Cu_Coil_Calibration_15-Mar-19.txt @@ -0,0 +1 @@ +0.0325,0.0325,0.0278 \ No newline at end of file