diff --git a/Chimera.py b/Chimera.py index 5d17ef5..55cb60c 100644 --- a/Chimera.py +++ b/Chimera.py @@ -1,322 +1,346 @@ 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("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.IVUseAlternatingV = True - self.LowerIV = 0.0 - self.HigherIV = 0.0 - self.StepIV = 0.0 + self.LowerIV = -2.0 + self.HigherIV = +2.0 + self.StepIV = 0.2 self.timeIV = 2 # 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('IVUseAlternatingV = ' + str(self.IVUseAlternatingV)) + print('LowerIV (V) = ' + str(self.LowerIV)) + print('HigherIV (V) = ' + str(self.HigherIV)) + 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): 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() 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) return ndown, nup 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(self.experimentName), '{}{}{}'.format('IV_', self.experimentName, nowstr) else: savingName = '{}'.format(self.experimentName), '{}{}'.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 ZeroVolt(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) def SetVoltage(self, sb, write=True): self.newbiasvalue = sb # self.ChimeraSettings.RestartBuffer = True if write: self.SaveVoltage() 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) now = datetime.datetime.now() csvstr = datetime.datetime.strftime(now, '%Y, %m, %d, %H, %M, %S') data = [csvstr, self.newbiasvalue] with open(fullpath, 'w') as csvfile: writeline = csv.writer(csvfile, delimiter=',') writeline.writerows(data) def WriteRawData(self): if self.saveDownsampled: 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.ChimeraSettings.displaysubsample else: samplerate = self.ChimeraSettings.ADCSAMPLERATE mdict = {'DisplayBuffer': len(self.displaybuffer), 'ADCSAMPLERATE': samplerate, 'mytimestamp': str(datetime.datetime.today()), 'bias2value': self.ChimeraSettings.newbiasvalue, 'SETUP_biasvoltage': self.ChimeraSettings.newbiasvalue, 'SETUP_ADCVREF': self.ChimeraSettings.ADCVREF, 'SETUP_ADCSAMPLERATE': self.ChimeraSettings.ADCSAMPLERATE, '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.myvoltageoffset} io.savemat(self.savename + '.mat', mdict, True, '5', False, False, 'row') def SaveData(self): if self.file is not None and not self.file.closed and self.ADClogsize < self.ChimeraSettings.MAXLOGBYTES: self.WriteRawData() else: # Create new filename self.CreateSavename() # open file and reset logsize self.file = open(self.savename + '.log') self.ADClogsize = 0 # Write summary .mat file and write raw .log file self.writeSummary() self.WriteRawData() 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_xdata(x) 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)