Page MenuHomec4science

Chimera.py
No OneTemporary

File Metadata

Created
Sat, May 11, 21:36

Chimera.py

import ChimeraSettings
import ok
import ChimeraControls
import os
import pickle
import datetime
import numpy as np
import time
import csv
import matplotlib.pyplot as plt
import functions
from scipy import io
from matplotlib.ticker import EngFormatter
Amp = EngFormatter(unit='A', places=2)
Time = EngFormatter(unit='s', places=2)
Volt = EngFormatter(unit='V', places=2)
Cond = EngFormatter(unit='S', places=2)
# Main Chimera Launcher
class Launcher:
def __init__(self, loadedInstance=None):
if loadedInstance is None:
self.ChimeraSettings = ChimeraSettings.ChimeraSettings()
if os.path.isfile("C:\\ChimeraPython\\store.pckl"):
self.ChimeraSettings.setStoredValues()
else:
self.ChimeraSettings = loadedInstance
# Initialize Chimera
self.xem = ok.FrontPanel()
ChimeraControls.InitializeChimera(self.ChimeraSettings, self.xem)
# Control variables
self.newbiasvalue = 0
# Set saving variables
self.DataFolder = None
self.todaysfolder = None
self.experimentName = None
self.file = None
self.savename = None
self.SetSavingFolder(os.getcwd())
self.ADClogsize = 0
self.saveDownsampled = False
# Plotting Variables
self.displaysubsample = 50
self.lowpass = 10e3
self.displaySamplerate = self.lowpass*2
# IV variables
self.MaxV_IV = 0.4
self.StepIV = 0.05
self.timeIV = 4
# Event detection
self.Threshold = 5 # standard deviations
self.DwellTime = .5 # in ms
self.upwardevents = False
# Data variables
self.blockvalues = np.empty((1048576,), dtype=np.uint16)
self.readvalues = ChimeraControls.ConvertBlockvalues(self.ChimeraSettings, self.blockvalues)
self.displaybuffer = np.empty((65536,), dtype=np.uint16)
self.ShowSettings()
def ShowSettings(self):
print('Settings:')
print('Saving variables:')
print('savename = ' + str(self.savename))
print('saveDownsampled = ' + str(self.saveDownsampled))
print('')
print('Plotting Variables:')
print('displaysubsample = ' + str(self.displaysubsample))
print('lowpass (Hz) = ' + str(self.lowpass))
print('')
print('IV variables:')
print('MaxV_IV (V) = ' + str(self.MaxV_IV))
print('StepIV (V) = ' + str(self.StepIV))
print('Time (s) = ' + str(self.timeIV))
print('')
print('Event Detection:')
print('Threshold (* st.dev) = ' + str(self.Threshold))
print('DwellTime (ms) = ' + str(self.DwellTime))
print('upwardevents = ' + str(self.upwardevents))
def Initialize(self):
self.xem = ok.FrontPanel()
ChimeraControls.InitializeChimera(self.ChimeraSettings, self.xem)
def ZeroCurrent(self):
measI = np.mean(self.RecordTrace())
self.ChimeraSettings.SETUP_pAoffset = self.ChimeraSettings.SETUP_pAoffset - measI * 1E-9
print('New current offset: {} '.format(Amp.format_data(self.ChimeraSettings.SETUP_pAoffset)))
self.ResetBuffer()
self.ChimeraSettings.saveStoredValues()
def EventDetection(self, useRaw=False, Threshold=None, DwellTime=None, upwardevents=None):
if Threshold is None:
Threshold = self.Threshold
if DwellTime is None:
DwellTime = self.DwellTime
if upwardevents is None:
upwardevents = self.upwardevents
if useRaw:
inputtrace = self.readvalues
DwellTimedp = DwellTime * 1e-6 * self.ChimeraSettings.ADCSAMPLERATE
else:
inputtrace = self.displaybuffer
DwellTimedp = DwellTime * 1e-6 * self.ChimeraSettings.ADCSAMPLERATE/self.displaysubsample
ndown = functions.EventDetection(inputtrace, Threshold, DwellTimedp)
if upwardevents:
nup = functions.EventDetection(inputtrace*-1, Threshold, DwellTime)
if ndown is False:
totalevents = nup
elif nup is False:
totalevents = ndown
else:
totalevents = ndown + nup
return totalevents
else:
return ndown
def SetSavingFolder(self, savingFolder=None, experimentName='Untitled'):
if savingFolder is not None:
self.DataFolder = savingFolder
self.todaysfolder = str(datetime.date.today())
self.experimentName = experimentName
if not os.path.exists(self.DataFolder):
os.makedirs(self.DataFolder)
if not os.path.exists(os.path.join(self.DataFolder, self.todaysfolder)):
os.makedirs(os.path.join(self.DataFolder, self.todaysfolder))
self.savename = os.path.join(self.DataFolder, self.todaysfolder, self.experimentName)
print('Files are saved in ' + self.savename)
def CreateSavename(self, IV=False):
savingFolder = os.path.join(self.DataFolder, self.todaysfolder)
now = datetime.datetime.now()
nowstr = datetime.datetime.strftime(now, '%Y%m%d_%H%M%S')
if IV:
savingName = '{}{}{}'.format('IV_', self.experimentName, nowstr)
else:
savingName = '{}{}'.format(self.experimentName, nowstr)
self.savename = os.path.join(savingFolder, savingName)
print('Savename: ' + self.savename)
def SetExperimentName(self, experimentName):
self.SetSavingFolder(self.DataFolder, experimentName=experimentName)
def SaveSettings(self, fileName):
with open(fileName, 'rb') as file:
pickle.dump(self.ChimeraSettings, file)
print('Saved as ' + fileName)
def LoadSettings(self, fileName):
with open(fileName, 'rb') as file:
self.ChimeraSettings = pickle.load(file)
print('Loaded from ' + fileName + '. Re-initializing...')
ChimeraControls.InitializeChimera(self.ChimeraSettings, self.xem)
def updateBW(self, printtext=True):
out = ChimeraControls.CHIMERA_bandwidthtimer(self.ChimeraSettings, self.xem)
if printtext:
text1 = "Time\n{0}\nUSB Read Rate\n{1:} kHz\nUSB Write Rate\n{2}".format(out['text_time'],
out['USB_readrate'],
out['USB_writerate'])
text2 = "Buffer\n{0} kB\nBuffer Size\n{1} %\nSeconds buffered\n{2:.3f} sec".format(out['buffer'],
out['bufferPC'],
out['bufferseconds'])
print(text1)
print(text2)
return out
def ResetBuffer(self):
print("Buffer is resetting...", end='')
self.xem.SetWireInValue(self.ChimeraSettings.EP_WIREIN_TEST1, self.ChimeraSettings.EPBIT_GLOBALRESET,
self.ChimeraSettings.EPBIT_GLOBALRESET)
self.xem.UpdateWireIns()
time.sleep(0.1)
self.xem.SetWireInValue(self.ChimeraSettings.EP_WIREIN_TEST1, 0, self.ChimeraSettings.EPBIT_GLOBALRESET)
self.xem.UpdateWireIns()
print('done')
def SetZeroVoltage(self, voltage):
self.ChimeraSettings.voltageOffset = voltage
self.ChimeraSettings.saveStoredValues()
def ZeroVoltage(self):
Vdelta = 0.02
print('Measuring at {} ...'.format(Volt.format_data(Vdelta)), end='')
self.SetVoltage(Vdelta, write=False)
self.ResetBuffer()
time.sleep(1)
measI1 = np.mean(self.RecordTrace())
print('{}'.format(Amp.format_data(measI1)))
print('Measuring at {} ...'.format(Volt.format_data(0)), end='')
self.SetVoltage(0, write=False)
self.ResetBuffer()
time.sleep(1)
measI2 = np.mean(self.RecordTrace())
print('{}'.format(Amp.format_data(measI2)))
deltaI = measI1-measI2
if deltaI == 0:
print('Error, cannot zero voltage: deltaI = 0')
else:
measR = Vdelta / deltaI
self.ResetBuffer()
self.ChimeraSettings.voltageOffset += -measI2 * measR
print('New voltage offset: {}'.format(Volt.format_data(self.ChimeraSettings.voltageOffset)))
ChimeraControls.CHIMERA_updateDACvalues1(self.ChimeraSettings, self.xem, 0)
self.SetVoltage(self.ChimeraSettings.voltageOffset)
self.ChimeraSettings.saveStoredValues()
def SetVoltage(self, sb, write=True):
if sb is not self.newbiasvalue:
self.newbiasvalue = sb
# self.ChimeraSettings.RestartBuffer = True
if write:
now = datetime.datetime.now()
time_string = now.time().strftime("%H:%M:%S")
print(time_string + ', {}'.format(Volt.format_data(sb)))
self.SaveVoltage()
self.file = None
ChimeraControls.CHIMERA_updateDACvalues1(self.ChimeraSettings, self.xem, self.newbiasvalue)
def RecordTraceRaw(self):
self.blockvalues = ChimeraControls.CHIMERA_process_triggers(self.ChimeraSettings, self.xem)
self.readvalues = ChimeraControls.ConvertBlockvalues(self.ChimeraSettings, self.blockvalues)
return self.readvalues
def RecordTrace(self):
self.RecordTraceRaw()
# Samplerate = self.ChimeraSettings.ADCSAMPLERATE
# displaybuffer, self.displaySamplerate = functions.LowPass(readvalues, self.ChimeraSettings, self.lowpass)
# displaybuffer = ChimeraControls.lowpass(self.ChimeraSettings, readvalues, cutoff=self.lowpass)
self.displaybuffer, self.displaySamplerate = \
functions.LowPassFast(self.readvalues, self.ChimeraSettings, self.displaysubsample, self.lowpass)
return self.displaybuffer
def SaveVoltage(self):
savingFolder = os.path.join(self.DataFolder, self.todaysfolder)
savingName = self.experimentName + 'Vdata.csv'
fullpath = os.path.join(savingFolder, savingName)
if not os.path.isfile(fullpath):
csv_headers = ['Date', 'Time', 'Voltage']
with open(fullpath, 'w') as new_data_file:
datawriter = csv.writer(new_data_file)
datawriter.writerow(csv_headers)
# Create date and time string
now = datetime.datetime.now()
date_string = now.date().strftime("%Y-%m-%d")
time_string = now.time().strftime("%H:%M:%S")
# Convert to data
data = [date_string, time_string, str(self.newbiasvalue)]
with open(fullpath, 'w') as csvfile:
writeline = csv.writer(csvfile, delimiter=',')
writeline.writerows(data)
def WriteRawData(self, saveVoltages=False):
if self.saveDownsampled:
if saveVoltages:
voltages = np.ones(len(self.displaybuffer)) * self.newbiasvalue * 1000
final = np.vstack((self.displaybuffer, voltages))
self.file.write((final.copy(order='C')))
else:
self.file.write(self.displaybuffer.copy(order='C'))
self.ADClogsize += 2 * len(self.displaybuffer)
else:
self.file.write(np.uint16(self.blockvalues))
self.ADClogsize += 2 * len(self.blockvalues)
def writeSummary(self):
if self.saveDownsampled:
samplerate = self.ChimeraSettings.ADCSAMPLERATE/self.displaysubsample
else:
samplerate = self.ChimeraSettings.ADCSAMPLERATE
mdict = {'DisplayBuffer': len(self.displaybuffer),
'ADCSAMPLERATE': samplerate,
'mytimestamp': str(datetime.datetime.today()),
'bias2value': self.newbiasvalue,
'SETUP_ADCVREF': self.ChimeraSettings.ADCVREF,
'SETUP_ADCSAMPLERATE': self.ChimeraSettings.ADCSAMPLERATE,
'SETUP_displaysubsample': self.displaysubsample,
'SETUP_ADCBITS': self.ChimeraSettings.ADCBITS,
'SETUP_TIAgain': self.ChimeraSettings.SETUP_TIAgain,
'SETUP_preADCgain': self.ChimeraSettings.SETUP_preADCgain,
'SETUP_pAoffset': self.ChimeraSettings.SETUP_pAoffset,
'SETUP_mVoffset': self.ChimeraSettings.voltageOffset}
io.savemat(self.savename + '.mat', mdict, True, '5', False, False, 'row')
def SaveData(self, close=True, saveVoltages=False):
if self.file is not None and self.ADClogsize < self.ChimeraSettings.MAXLOGBYTES:
if not self.file.closed:
self.WriteRawData(saveVoltages)
else:
self.file = open(self.savename + '.log', 'ab')
self.WriteRawData(saveVoltages)
if close:
self.file.close()
else:
if self.file is not None and not self.file.closed:
self.file.close()
# Create new filename
self.CreateSavename()
# open file and reset logsize
self.file = open(self.savename + '.log', 'ab')
self.ADClogsize = 0
# Write summary .mat file and write raw .log file
self.writeSummary()
self.WriteRawData(saveVoltages)
if close:
self.file.close()
def MakeIV(Chimera):
MaxV_IV = Chimera.MaxV_IV
StepIV = Chimera.StepIV
timeIV = Chimera.timeIV
allVoltages = functions.MakeAllVoltagesForIV(StepIV, MaxV_IV)
# Set Chimera functions:
oldlowpass = Chimera.lowpass
olddisplaysubsample = Chimera.displaysubsample
oldsaveDownsampled = Chimera.saveDownsampled
Chimera.saveDownsampled = True
Chimera.lowpass = 2e3
Chimera.displaysubsample = 100
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))
ax1.set_xlabel('time (s)')
ax1.set_ylabel('current (nA)')
ax1.set_xlim([0, timeIV])
ax1.set_title('Time plot')
ax2.set_xlabel('Voltage (V)')
ax2.set_ylabel('current (nA)')
ax2.set_title('IV-plot')
ax2.set_xlim([-MaxV_IV, MaxV_IV])
plt.tight_layout()
currents = []
voltagesScanned = []
# Loop over all voltages
for i in range(len(allVoltages)):
# Set voltage value
currentVoltage = allVoltages[i]
voltagesScanned.append(currentVoltage)
Chimera.SetVoltage(currentVoltage, write=False)
t_end = time.time() + timeIV
tVal = []
yVal = []
# Record trace for timeIV seconds
while time.time() < t_end:
trace = Chimera.RecordTrace()
Chimera.SaveData(saveVoltages=True)
tVal.append(time.time() - t_end + timeIV)
yVal.append(np.mean(trace))
# Live plot recording data
if ax1.lines:
for line in ax1.lines:
line.set_xdata(tVal)
line.set_ydata(yVal)
else:
ax1.plot(tVal, yVal)
plt.show(block=True)
ax1.set_ylim([min(yVal) - 0.1 * abs(min(yVal)), max(yVal) + 0.1 * abs(max(yVal))])
fig.canvas.draw()
fig.canvas.flush_events()
# Make list for plotting live plotting basic I-V
currents.append(yVal[-1])
voltagesScanned, currents = (list(t) for t in zip(*sorted(zip(voltagesScanned, currents))))
# Live plotting I-V
if ax2.lines:
for line in ax2.lines:
line.set_xdata(voltagesScanned)
line.set_ydata(currents)
else:
ax2.plot(voltagesScanned, currents)
plt.show(block=True)
ax2.set_ylim([min(currents) - 0.1 * abs(min(currents)), max(currents) + 0.1 * abs(max(currents))])
fig.canvas.draw()
fig.canvas.flush_events()
# Return filename
filename = Chimera.savename + '.log'
# Reset parameters
Chimera.lowpass = oldlowpass
Chimera.displaysubsample = olddisplaysubsample
Chimera.saveDownsampled = oldsaveDownsampled
return filename
class ChimeraPlot:
def __init__(self, Chimera):
self.Chimera = Chimera
self.fig, self.ax = plt.subplots(figsize=(9.5, 4.5))
self.ax.set_xlabel('Time [s]')
self.ax.set_ylabel('Current [nA]')
self.ax.set_title(self.Chimera.savename)
self.buffertext = plt.figtext(0.95, 0.5, '')
self.samplerate = Chimera.ChimeraSettings.ADCSAMPLERATE/Chimera.displaysubsample
self.buffercheck = 5
def Update(self, trace):
x = np.arange(len(trace)) / self.samplerate
currentIDC = np.mean(trace)
currentRMS = np.std(trace)
if self.ax.lines:
for line in self.ax.lines:
line.set_ydata(trace)
else:
self.ax.plot(x, trace)
plt.show(block=False)
self.fig.canvas.draw()
self.ax.set_ylim([currentIDC - 10 * currentRMS, currentIDC + 10 * currentRMS])
self.ax.set_xlim([0, len(trace)/self.samplerate])
self.fig.canvas.draw()
self.fig.canvas.flush_events()
def Writebuffer(self, out):
textstr = "Buffer\n{0} kB\nBuffer Size\n{1} %\nSeconds buffered\n{2:.3f} sec".format(out['buffer'],
out['bufferPC'],
out['bufferseconds'])
self.buffertext.set_text(textstr)

Event Timeline