Beispiel #1
0
    def populateUi(self):
        s = QSettings(OrganizationName, ApplicationName)
        d = daq.Device(1)
        gains = d.aiGains()
        ranges = [d.rangeForAiGain(gain) for gain in gains]
        nChannels = d.aiChannels
        fMin = d.sampleRateSpan[0]
        fMax = d.sampleRateSpan[1]
        del d
        self.sampleRateSb.setMinimum(fMin/1E3)
        self.sampleRateSb.setMaximum(fMax/1E3)
        self.sampleRateSb.setValue(s.value('sampleRate', 10E3, type=float))
        self.chunkTimeSb.setValue(s.value('chunkTime', 0.5, type=float))
        self.nameLe.setText(s.value('name', '', type=str))
        self.commentLe.setText(s.value('comment', '', type=str))
        self.lpfOrderSb.setValue(s.value('lpfOrder', 0, type=int))
        self.lpfFrequencySb.setValue(s.value('lpfFrequency', 0.1*fMax/1E3, type=float))
        self.resampleRateSb.setValue(s.value('resampleRateSb', 0.2*fMax/1E3, type=float))
        self.enablePlottingCb.setChecked(s.value('enablePlotting', True, type=bool))

        try:
            self.remote = OpenSquidRemote(port = 7894)
            squids = self.remote.findSquids()
            if squids is None:
                squids = []
        except Exception, e:
            print "OpenSQUID remote failed:", e
            squids = []
Beispiel #2
0
    origin = 'NoiseVdTemperature'
    app = QApplication([])
    hdfFile = hdf.File('NoiseVsT_%s_20180130.h5' % device)
    hdfFile.attrs['program'] = origin
    hdfFile.attrs['Control'] = 'RuOx2005'
    hdfFile.attrs['Device'] = device
    hdfFile.attrs['aiChannel'] = str(aiChannel.physicalChannel)
    hdfFile.attrs['Ts'] = baseTs

    hkGroup = hdfFile.require_group('HK')
    hkSub = HousekeepingSubscriber()
    hkSub.start()
    hkLogger = HkLogger(hkGroup, hkSub)

    osr = OpenSquidRemote(port=7894, origin=origin)

    squid = Pfl102Remote(osr, device)
    squid.setFeedbackR(100E3)
    squid.setFeedbackC(1.5E-9)
    x = tuneStage1OutputToZero(squid, aiChannel)

    adr = Adr(app)

    from DAQ.AiSpectrumAnalyzerRemote import AiSpectrumAnalyzerRemote
    sa = AiSpectrumAnalyzerRemote('test')
    sa.setSampleRate(2E6)
    sa.setMaxCount(300)
    sa.setRefreshTime(0.1)

    for baseTindex, baseT in enumerate(baseTs):
        time.sleep(1)

    while time.time() - t0 < seconds:
        time.sleep(0.1)


if __name__ == '__main__':
    import logging
    logger = logging.getLogger('')
    logger.setLevel(logging.INFO)
    #ch = logging.StreamHandler()
    #logger.addHandler(ch)
    app = QApplication([])

    aiChannel = daq.AiChannel('USB6361/ai7', -10, +10)
    osr = OpenSquidRemote(port=7894, origin='NoiseVsBiasAndTemperature')

    device = 'TES2'
    squid = Pfl102Remote(osr, device)
    squid.setFeedbackR(100E3)
    squid.setFeedbackC(15E-9)
    x = tuneStage1OutputToZero(squid, aiChannel)
    print(x)
    print(squid.report())
    print(squid.stage1OffsetCurrent())

    adr = Adr(app)

    #Rbias = 1697.5 # TES 1
    Rbias = 1601.7  # TES 2
Beispiel #4
0
#Rb =  6.8735E3
#Ibiases = np.asarray([150E-6, -150E-6, 200E-6, -200E-6])
#Ibiases = np.asarray([-400E-6])
#Vbiases = Ibiases*Rb
step = 0.1
Vbiases = np.hstack([[0],
                     np.arange(5, 1.5, -0.1),
                     np.arange(1.5, 0.6, -0.005), [0]])
Vbiases = np.hstack([[0], np.arange(1.5, 0, -0.005), [0]])

#Vbiases = np.hstack([np.arange(1.04, 0.8, -0.010), [0]])

app = QCoreApplication([])
ivRemote = IvCurveDaqRemote.IvCurveDaqRemote('TesIvsB_vsBiasSteps')
print(ivRemote.auxAoVoltage())
osr = OpenSquidRemote(port=7894)
pfl = Pfl102Remote(osr, device)


def waitForSweeps(remote, n=1):
    count = ivRemote.sweepCount()
    newCount = 0
    while newCount < count + n:
        time.sleep(1)
        app.processEvents()
        newCount = ivRemote.sweepCount()


ivRemote.setAuxAoVoltage(Vbiases[0])
time.sleep(2)
Beispiel #5
0
def collectVPhiCurves(device, hdfRoot, biasCurrents):
    osr = OpenSquidRemote(port = 7894)
    pfl = Pfl102Remote(osr, device)
    pfl.setTestSignal('Off')
    pfl.setTestInput('SQUID flux')
    channel = bytes(pfl.daqDevice()+'/'+pfl.daqChannel())
    refChannel = bytes(pfl.daqDevice()+'/'+pfl.daqReferenceChannel())
    triggerTerminal = bytes(pfl.daqTrigger())
    print('Channel:', channel)
    aiChannel = daq.AiChannel(channel, -5, +5)
    aiChannel.setTerminalConfiguration(daq.AiChannel.TerminalConfiguration.DIFF)

    aiRefChannel = daq.AiChannel(refChannel, -2, +2)
    aiRefChannel.setTerminalConfiguration(daq.AiChannel.TerminalConfiguration.DIFF)
    
    pfl.lockStage2()
    pfl.setStage1OffsetCurrent(0)
    tuneStage2OutputToZero(pfl, aiChannel)
    pfl.setTestSignal('On')

    fs = 500E3
    samples = int(fs*0.09)
    timing = daq.Timing(rate=fs)
    timing.setSamplesPerChannel(samples)
    timing.setSampleMode(daq.Timing.SampleMode.FINITE)
        
    g = hdfRoot.create_group('V-Phi')
    g.attrs['device'] = device
    g.attrs['sampleRate'] = timing.rate

    aiTaskR = daq.AiTask('aiRef')
    aiTaskR.addChannel(aiRefChannel)
    aiTaskR.configureTiming(timing)
    aiTaskR.digitalEdgeStartTrigger(triggerTerminal, daq.Edge.RISING)
    rsRef = RunningStats()
    for i in range(10):
        aiTaskR.start()
        while aiTaskR.samplesAvailable() < samples:
            print('.', end='')
            time.sleep(0.05)
        d = aiTaskR.readData(samples)[0]
        aiTaskR.stop()
        rsRef.push(d)
    g.attrs['FgChannel'] = refChannel
    g.create_dataset('FgMean', data=rsRef.mean())
    g.create_dataset('FgStd', data=rsRef.std())
    g.attrs['report'] = str(pfl.report())
    g.attrs['biasCurrents'] = biasCurrents

    aiTask = daq.AiTask('aiPfl')
    aiTask.addChannel(aiChannel)
    aiTask.configureTiming(timing)
    aiTask.digitalEdgeStartTrigger(triggerTerminal, daq.Edge.RISING)
    
    #import matplotlib.pyplot as mpl
    pfl.setTestSignal('On')
    
    for biasCurrent in biasCurrents:
        print('Current:', biasCurrent)
        pfl.setStage1BiasCurrent(biasCurrent)
        time.sleep(0.2)
        print('Acquiring', end='')
        rs = RunningStats()
        for i in range(20):
            aiTask.start()
            while aiTask.samplesAvailable() < samples:
                print('.', end='')
                time.sleep(0.05)
            d = aiTask.readData(samples)[0]
            rs.push(d)
            #print(d.shape)
            aiTask.stop()
        #mpl.plot(rs.mean())
        sg = g.create_group('Bias%07.0fuA' % (biasCurrent*1E6))
        sg.create_dataset('PflMean', data=rs.mean())
        sg.create_dataset('PflStd', data=rs.std())
        sg.attrs['biasCurrent'] = pfl.stage1BiasCurrent()
        sg.attrs['Channel'] = channel
Beispiel #6
0
        sg = g.create_group('Bias%07.0fuA' % (biasCurrent*1E6))
        sg.create_dataset('PflMean', data=rs.mean())
        sg.create_dataset('PflStd', data=rs.std())
        sg.attrs['biasCurrent'] = pfl.stage1BiasCurrent()
        sg.attrs['Channel'] = channel
        
    #mpl.show()

if __name__ == '__main__':
    import numpy as np
    from OpenSQUID.OpenSquidRemote import OpenSquidRemote, Pfl102Remote
    from SquidHelper import tuneStage2OutputToZero
    import DAQ.PyDaqMx as daq
    import time
    #from Utility.RunningStats import RunningStats
    from Utility.RunningStats import RunningStats

    device = 'TES2'
    offsetCurrents = np.linspace(1.30E-6, 7.5E-6, 51)
    biasCurrents = np.linspace(10E-6, 300E-6, 61)
    
    osr = OpenSquidRemote(port = 7894, origin='SquidIvCurves')
    ifc = osr.obtainInterfaceRemote('PCI-1000')
    fg = ifc.functionGenerator()

    with hdf.File('SQUID_%s_075mK_Vac50mV_fac321kHz_%s.h5' % (device,time.strftime('%Y%m%d_%H%M%S')), 'a') as f:
        fg.setAmplitude(3.0)
        collectIvCurves(device, f, offsetCurrents)
        fg.setAmplitude(1.0)
        collectVPhiCurves(device, f, biasCurrents)
Beispiel #7
0
class DaqStreamingWidget(Ui.Ui_Form, QWidget):
    def __init__(self, parent = None):
        super(DaqStreamingWidget, self).__init__(parent)
        self.setupUi(self)
        self.thread = None
        self.hdfFile = None
        self.columns = {'enabled':0, 'save': 1, 'coupling':2, 'mode':3, 'gain':4, 'squid':5, 'reset':6, 'label':7}
        self.plot.addLegend()
        self.plot.setLabel('left', 'voltage', units='V')
        self.plot.setLabel('bottom', 'time', units='s')
        self.curves = []
        self.runPb.clicked.connect(self.runPbClicked)
        self.bFilter = []
        self.aFilter = []
        self.populateUi()
        self.publisher = ZmqPublisher('LegacyDaqStreaming', port=PubSub.LegacyDaqStreaming)
        self.writeDataPb.toggled.connect(self.writeDataToggled)
        
    def populateUi(self):
        s = QSettings(OrganizationName, ApplicationName)
        d = daq.Device(1)
        gains = d.aiGains()
        ranges = [d.rangeForAiGain(gain) for gain in gains]
        nChannels = d.aiChannels
        fMin = d.sampleRateSpan[0]
        fMax = d.sampleRateSpan[1]
        del d
        self.sampleRateSb.setMinimum(fMin/1E3)
        self.sampleRateSb.setMaximum(fMax/1E3)
        self.sampleRateSb.setValue(s.value('sampleRate', 10E3, type=float))
        self.chunkTimeSb.setValue(s.value('chunkTime', 0.5, type=float))
        self.nameLe.setText(s.value('name', '', type=str))
        self.commentLe.setText(s.value('comment', '', type=str))
        self.lpfOrderSb.setValue(s.value('lpfOrder', 0, type=int))
        self.lpfFrequencySb.setValue(s.value('lpfFrequency', 0.1*fMax/1E3, type=float))
        self.resampleRateSb.setValue(s.value('resampleRateSb', 0.2*fMax/1E3, type=float))
        self.enablePlottingCb.setChecked(s.value('enablePlotting', True, type=bool))

        try:
            self.remote = OpenSquidRemote(port = 7894)
            squids = self.remote.findSquids()
            if squids is None:
                squids = []
        except Exception, e:
            print "OpenSQUID remote failed:", e
            squids = []
        
         
        table = self.channelTable
        table.setRowCount(nChannels)
        table.setVerticalHeaderLabels(['CH%d' % ch for ch in range(nChannels)])
        s.beginReadArray('ChannelSettings')
        for ch in range(nChannels):
            s.setArrayIndex(ch)
            gainCombo = QComboBox()
            for gain, fs in zip(gains, ranges):
                gainCombo.addItem(u'%+2ddB (±%.3f V)' % (gain, fs), userData=gain)
            gainCombo.setCurrentIndex(gainCombo.findData(s.value('gain', 0, type=int)))
            
            squidCombo = QComboBox()
            squidCombo.addItem('None')
            squidCombo.addItems(squids)
            squidCombo.setCurrentIndex(squidCombo.findText(s.value('squid', 'None', type=QString)))
            
            resetSb = QDoubleSpinBox()
            resetSb.setMinimum(0)
            resetSb.setMaximum(10)
            resetSb.setDecimals(2)
            resetSb.setSingleStep(0.01)
            resetSb.setAccelerated(True)
            resetSb.setValue(s.value('reset', 0, type=float))
 
            modeCombo = QComboBox()
            modeCombo.addItem('SE')
            modeCombo.addItem('DIFF')
            modeCombo.setCurrentIndex(modeCombo.findText(s.value('mode', 'SE', type=QString)))
            modeCombo.setToolTip('Select single-ended (SE) or differential (DIFF) input coupling via the switches on the break-out box. This setting is for informational purposes only.')
            
            couplingCombo = QComboBox()                
            couplingCombo.addItem('AC')
            couplingCombo.addItem('DC')
            couplingCombo.setCurrentIndex(couplingCombo.findText(s.value('coupling', 'AC', type=QString)))
            
            enabledCb = QCheckBox()
            enabledCb.setChecked(s.value('enabled', False, type=bool))
            saveCb = QCheckBox()
            saveCb.setChecked(s.value('save', False, type=bool))
            lpfSb = QDoubleSpinBox()
            lpfSb.setMinimum(0.1*fMax/1E3)
            lpfSb.setMaximum(0.5*fMax/1E3)
            lpfSb.setSuffix(' kHz')
            lpfSb.setValue(s.value('lpCutOffFrequency', 0, type=float))
            lpfOrderSb = QSpinBox()
            lpfOrderSb.setMinimum(0)
            lpfOrderSb.setMaximum(6)
            lpfOrderSb.setSpecialValueText('Off')
            lpfOrderSb.setValue(s.value('lpfOrder', 0, type=int))
            labelLe = QLineEdit()
            table.setCellWidget(ch, self.columns['enabled'], enabledCb)
            table.setCellWidget(ch, self.columns['save'], saveCb)
            table.setCellWidget(ch, self.columns['gain'], gainCombo)
            table.setCellWidget(ch, self.columns['mode'], modeCombo)
            table.setCellWidget(ch, self.columns['coupling'], couplingCombo)
            table.setCellWidget(ch, self.columns['squid'], squidCombo)
            table.setCellWidget(ch, self.columns['reset'], resetSb)
            table.setCellWidget(ch, self.columns['label'], labelLe)
        s.endArray()
        table.resizeColumnsToContents()
Beispiel #8
0
    def __init__(self, parent=None):
        super(IvCurveWidget, self).__init__(parent)
        self.setupUi(self)
        self.restartPb.clicked.connect(self.restart)
        self.thread = None
        self.hdfFile = None
        self.squid = None
        self._fileName = ''
        self.plot.addLegend()
        self.plot.setLabel('left', 'SQUID response', units='V')
        self.plot.setLabel('bottom', 'bias voltage', units='V')
        self.curves = []
        self.startPb.clicked.connect(self.startMeasurement)
        self.stopPb.clicked.connect(self.stopMeasurement)

        #        self.aoRangeCombo.currentIndexChanged.connect(self.updateAoRange)
        #        self.auxAoChannelCombo.currentIndexChanged.connect(self.updateAuxAoRange)

        self.osr = OpenSquidRemote(port=7894)
        squids = self.osr.findSquids()
        self.tesCombo.addItem('None')
        self.tesCombo.addItems(squids)

        self.settingsWidgets = [
            self.deviceCombo, self.aoChannelCombo, self.aoRangeCombo,
            self.aiChannelCombo, self.aiRangeCombo, self.aiTerminalConfigCombo,
            self.aiDriveChannelCombo, self.recordDriveCb, self.maxDriveSb,
            self.slewRateSb, self.zeroHoldTimeSb, self.peakHoldTimeSb,
            self.betweenHoldTimeSb, self.decimateCombo, self.sampleRateSb,
            self.sampleLe, self.commentLe, self.enablePlotCb,
            self.auxAoChannelCombo, self.auxAoRangeCombo, self.auxAoSb,
            self.auxAoEnableCb, self.polarityCombo, self.tesCombo,
            self.pflResetCb, self.driveOffsetSb
        ]
        self.deviceCombo.currentIndexChanged.connect(self.updateDevice)
        for w in [
                self.maxDriveSb, self.slewRateSb, self.zeroHoldTimeSb,
                self.peakHoldTimeSb, self.betweenHoldTimeSb, self.sampleRateSb
        ]:
            w.valueChanged.connect(self.updateInfo)
        self.decimateCombo.currentIndexChanged.connect(self.updateInfo)
        self.polarityCombo.currentIndexChanged.connect(self.updateInfo)
        self.auxAoSb.valueChanged.connect(self.updateAuxOutputVoltage)
        self.auxAoEnableCb.toggled.connect(self.toggleAuxOut)
        self.auxAoRamper = None
        self.restoreSettings()
        self.hkSub = HousekeepingSubscriber(self)
        self.hkSub.adrTemperatureReceived.connect(self.temperatureSb.setValue)
        self.hkSub.adrResistanceReceived.connect(self.collectAdrResistance)
        self.hkSub.start()

        self.serverThread = RequestReplyThreadWithBindings(
            port=RequestReply.IvCurveDaq, parent=self)
        boundWidgets = {
            'sampleName': self.sampleLe,
            'auxAoEnable': self.auxAoEnableCb,
            'auxVoltage': self.auxAoSb,
            'maxDrive': self.maxDriveSb,
            'slewRate': self.slewRateSb,
            'start': self.startPb,
            'stop': self.stopPb,
            'totalTime': self.totalTimeSb,
            'sweepCount': self.sweepCountSb,
            'comment': self.commentLe,
            'driveOffset': self.driveOffsetSb
        }
        for name in boundWidgets:
            self.serverThread.bindToWidget(name, boundWidgets[name])
        self.serverThread.bindToFunction('fileName', self.fileName)
        self.serverThread.bindToFunction('restart', self.requestRestart)
        self.serverThread.start()

        pens = 'rgbc'
        for i in range(4):
            curve = pg.PlotDataItem(pen=pens[i], name='Curve %d' % i)
            self.plot.addItem(curve)
            self.curves.append(curve)

        self.restartRequested = False
        timer = QTimer(self)
        timer.timeout.connect(self.checkRestartRequested)
        timer.setInterval(1000)
        timer.start()
        self.timer = timer
        self.logger.info('IvCurveDaq started.')
Beispiel #9
0
class IvCurveWidget(ui.Ui_Form, QWidget):
    EXIT_CODE_REBOOT = -1234
    logger = logging.getLogger('PulseCollectorMainWindow')

    def __init__(self, parent=None):
        super(IvCurveWidget, self).__init__(parent)
        self.setupUi(self)
        self.restartPb.clicked.connect(self.restart)
        self.thread = None
        self.hdfFile = None
        self.squid = None
        self._fileName = ''
        self.plot.addLegend()
        self.plot.setLabel('left', 'SQUID response', units='V')
        self.plot.setLabel('bottom', 'bias voltage', units='V')
        self.curves = []
        self.startPb.clicked.connect(self.startMeasurement)
        self.stopPb.clicked.connect(self.stopMeasurement)

        #        self.aoRangeCombo.currentIndexChanged.connect(self.updateAoRange)
        #        self.auxAoChannelCombo.currentIndexChanged.connect(self.updateAuxAoRange)

        self.osr = OpenSquidRemote(port=7894)
        squids = self.osr.findSquids()
        self.tesCombo.addItem('None')
        self.tesCombo.addItems(squids)

        self.settingsWidgets = [
            self.deviceCombo, self.aoChannelCombo, self.aoRangeCombo,
            self.aiChannelCombo, self.aiRangeCombo, self.aiTerminalConfigCombo,
            self.aiDriveChannelCombo, self.recordDriveCb, self.maxDriveSb,
            self.slewRateSb, self.zeroHoldTimeSb, self.peakHoldTimeSb,
            self.betweenHoldTimeSb, self.decimateCombo, self.sampleRateSb,
            self.sampleLe, self.commentLe, self.enablePlotCb,
            self.auxAoChannelCombo, self.auxAoRangeCombo, self.auxAoSb,
            self.auxAoEnableCb, self.polarityCombo, self.tesCombo,
            self.pflResetCb, self.driveOffsetSb
        ]
        self.deviceCombo.currentIndexChanged.connect(self.updateDevice)
        for w in [
                self.maxDriveSb, self.slewRateSb, self.zeroHoldTimeSb,
                self.peakHoldTimeSb, self.betweenHoldTimeSb, self.sampleRateSb
        ]:
            w.valueChanged.connect(self.updateInfo)
        self.decimateCombo.currentIndexChanged.connect(self.updateInfo)
        self.polarityCombo.currentIndexChanged.connect(self.updateInfo)
        self.auxAoSb.valueChanged.connect(self.updateAuxOutputVoltage)
        self.auxAoEnableCb.toggled.connect(self.toggleAuxOut)
        self.auxAoRamper = None
        self.restoreSettings()
        self.hkSub = HousekeepingSubscriber(self)
        self.hkSub.adrTemperatureReceived.connect(self.temperatureSb.setValue)
        self.hkSub.adrResistanceReceived.connect(self.collectAdrResistance)
        self.hkSub.start()

        self.serverThread = RequestReplyThreadWithBindings(
            port=RequestReply.IvCurveDaq, parent=self)
        boundWidgets = {
            'sampleName': self.sampleLe,
            'auxAoEnable': self.auxAoEnableCb,
            'auxVoltage': self.auxAoSb,
            'maxDrive': self.maxDriveSb,
            'slewRate': self.slewRateSb,
            'start': self.startPb,
            'stop': self.stopPb,
            'totalTime': self.totalTimeSb,
            'sweepCount': self.sweepCountSb,
            'comment': self.commentLe,
            'driveOffset': self.driveOffsetSb
        }
        for name in boundWidgets:
            self.serverThread.bindToWidget(name, boundWidgets[name])
        self.serverThread.bindToFunction('fileName', self.fileName)
        self.serverThread.bindToFunction('restart', self.requestRestart)
        self.serverThread.start()

        pens = 'rgbc'
        for i in range(4):
            curve = pg.PlotDataItem(pen=pens[i], name='Curve %d' % i)
            self.plot.addItem(curve)
            self.curves.append(curve)

        self.restartRequested = False
        timer = QTimer(self)
        timer.timeout.connect(self.checkRestartRequested)
        timer.setInterval(1000)
        timer.start()
        self.timer = timer
        self.logger.info('IvCurveDaq started.')

    def checkRestartRequested(self):
        if self.restartRequested:
            self.restart()

    def requestRestart(self):
        print('Restarting soon!')
        self.restartRequested = True
        return True

    def restart(self):
        if self.thread is not None:
            result = QMessageBox.question(
                self, "Restart program",
                "The measurement thread is still running. Do you really want to restart the program?",
                QMessageBox.Yes, QMessageBox.No)
            if result != QMessageBox.Yes:
                return
            self.thread.stop()
            self.thread.wait(3000)
        self.close()
        self.logger.info('IvCurveDaq restarting.')
        qApp.exit(self.EXIT_CODE_REBOOT)

    def fileName(self):
        return self._fileName

    def toggleAuxOut(self, enabled):
        if enabled:
            deviceName = str(self.deviceCombo.currentText())
            aoChannel = str(self.auxAoChannelCombo.currentText())
            aoRange = self.aoRanges[self.auxAoRangeCombo.currentIndex()]
            self.auxAoRamper = AuxAoRamper(deviceName, aoChannel, aoRange)
            self.auxAoRamper.setTo(self.auxAoSb.value())
        else:
            del self.auxAoRamper
            self.auxAoRamper = None

    def threadRunning(self):
        if self.thread is not None:
            return self.thread.isRunning()
        else:
            return False

    def updateAuxOutputVoltage(self):
        V = self.auxAoSb.value()
        if self.threadRunning():
            self.thread.updateAoVoltage(V)
        elif self.auxAoRamper is not None:
            try:
                self.auxAoRamper.rampTo(V)
            except Exception:
                exceptionString = traceback.format_exc()
                self.reportError(exceptionString)

#    def updateAuxAoRange(self):
#        #auxAoChannel = str(self.auxAoChannelCombo.currentText())
#        r = self.aoRanges[self.auxAoRangeCombo.currentIndex()]
#        #self.auxAoSb.setMaximum(r.max)
#        #self.auxAoSb.setMinimum(r.min)
#        if self.auxAoEnableCb.isChecked(): # If output is already on, we have to kill the old task and make a new one
#            self.toggleAuxOut(False)
#            self.toggleAuxOut(True)

    def collectAdrResistance(self, R):
        if self.hdfFile is None:
            return

        timeStamp = time.time()
        self.dsTimeStamps.resize((self.dsTimeStamps.shape[0] + 1, ))
        self.dsTimeStamps[-1] = timeStamp

        self.dsAdrResistance.resize((self.dsAdrResistance.shape[0] + 1, ))
        self.dsAdrResistance[-1] = R

    def populateDevices(self):
        self.deviceCombo.clear()
        system = daq.System()
        devices = system.findDevices()
        for dev in devices:
            self.deviceCombo.addItem(dev)


#    def updateAoRange(self):
#        aoRange = self.aoRanges[self.aoRangeCombo.currentIndex()]
#        self.maxDriveSb.setMaximum(aoRange.max)

    def updateDevice(self):
        self.aiChannelCombo.clear()
        self.aiDriveChannelCombo.clear()
        self.aoChannelCombo.clear()
        self.aiRangeCombo.clear()
        self.aoRangeCombo.clear()
        self.auxAoRangeCombo.clear()
        self.auxAoChannelCombo.clear()

        deviceName = str(self.deviceCombo.currentText())
        if len(deviceName) < 1:
            return
        device = daq.Device(deviceName)

        aiChannels = device.findAiChannels()
        for channel in aiChannels:
            self.aiChannelCombo.addItem(channel)
            self.aiDriveChannelCombo.addItem(channel)

        aoChannels = device.findAoChannels()
        for channel in aoChannels:
            self.aoChannelCombo.addItem(channel)
            self.auxAoChannelCombo.addItem(channel)

        self.aiRanges = device.voltageRangesAi()
        for r in self.aiRanges:
            self.aiRangeCombo.addItem('%+.2f -> %+.2f V' % (r.min, r.max))

        self.aoRanges = device.voltageRangesAo()
        for r in self.aoRanges:
            self.aoRangeCombo.addItem('%+.2f -> %+.2f V' % (r.min, r.max))
            self.auxAoRangeCombo.addItem('%+.2f -> %+.2f V' % (r.min, r.max))

        if len(aiChannels):
            aiChannel = daq.AiChannel('%s/%s' % (deviceName, aiChannels[0]),
                                      self.aiRanges[0].min,
                                      self.aiRanges[0].max)
            aiTask = daq.AiTask('TestInputSampleRate')
            aiTask.addChannel(aiChannel)
            aiSampleRate = aiTask.maxSampleClockRate()
        else:
            aiSampleRate = 0

        if len(aoChannels):
            aoChannel = daq.AoChannel('%s/%s' % (deviceName, aoChannels[0]),
                                      self.aoRanges[0].min,
                                      self.aoRanges[0].max)
            aoTask = daq.AoTask('TestOutputSampleRate')
            aoTask.addChannel(aoChannel)
            aoSampleRate = aoTask.maxSampleClockRate()
        else:
            aoSampleRate = 0

        rate = min(aiSampleRate, aoSampleRate)
        self.sampleRateSb.setMaximum(int(1E-3 * rate))
        self.updateInfo()

    def terminalConfiguration(self):
        t = str(self.aiTerminalConfigCombo.currentText())
        tc = daq.AiChannel.TerminalConfiguration
        terminalConfigDict = {'RSE': tc.RSE, 'DIFF': tc.DIFF, 'NRSE': tc.NRSE}
        return terminalConfigDict[t]

    def updateInfo(self):
        tz = self.zeroHoldTimeSb.value()
        tr = self.maxDriveSb.value() / self.slewRateSb.value()
        tp = self.peakHoldTimeSb.value()
        tb = self.betweenHoldTimeSb.value()
        f = self.sampleRateSb.value() * 1E3
        polarity = self.polarityCombo.currentText()
        if polarity == 'bipolar':
            ttotal = 2 * tz + 2 * (2 * tr + tp) + tb
        elif polarity == 'IvsB':
            ttotal = 2 * tz + 4 * tr + tb
        else:
            ttotal = 2 * tz + 1 * (2 * tr + tp)
        self.ttotal = ttotal
        self.totalTimeSb.setValue(ttotal)
        samplesPerSweep = int(
            np.ceil(ttotal * f / float(self.decimateCombo.currentText())))
        self.samplesPerSweepSb.setValue(samplesPerSweep)

    def restoreSettings(self):
        s = QSettings(OrganizationName, ApplicationName)
        self.populateDevices()
        for w in self.settingsWidgets:
            restoreWidgetFromSettings(s, w)

    def saveSettings(self):
        s = QSettings(OrganizationName, ApplicationName)
        for w in self.settingsWidgets:
            saveWidgetToSettings(s, w)

    def closeEvent(self, event):
        if self.thread is not None:
            event.ignore()
            return
        self.saveSettings()
        super(IvCurveWidget, self).closeEvent(event)

    def removeAllCurves(self):
        for curve in self.curves:
            curve.setData([], [])
        self.nSweeps = 0
        self.sweepCountSb.setValue(self.nSweeps)

    def startMeasurement(self):
        self.removeAllCurves()

        f = self.sampleRateSb.value() * 1E3
        Voffset = self.driveOffsetSb.value()
        Vmax = self.maxDriveSb.value()

        polarity = self.polarityCombo.currentText()

        if polarity == 'IvsB':
            whold1 = -Vmax * np.ones(int(self.zeroHoldTimeSb.value() * f))
            wrs = np.linspace(-Vmax, +Vmax,
                              int(2 * Vmax / self.slewRateSb.value() * f))
            whold2 = Vmax * np.ones(
                (int(self.betweenHoldTimeSb.value() * f), ), dtype=float)
            wave = np.hstack([whold1, wrs, whold2, wrs[::-1], whold1])
        else:
            wz = np.zeros((int(self.zeroHoldTimeSb.value() * f), ),
                          dtype=float)  # Zero
            wr = np.linspace(0, Vmax,
                             int(Vmax / self.slewRateSb.value() * f))  # Ramp
            wp = np.ones((int(self.peakHoldTimeSb.value() * f), ),
                         dtype=float) * Vmax  # Hold at peak
            wb = np.zeros((int(self.betweenHoldTimeSb.value() * f), ),
                          dtype=float)  # Hold between

            if polarity == 'bipolar':
                wave = np.hstack(
                    [wz, wr, wp, wr[::-1], wb, -wr, -wp, -wr[::-1],
                     wz])  # Up down and back
            elif polarity == 'positive only':
                wave = np.hstack([wz, wr, wp, wr[::-1], wz])  # Positive only
            elif polarity == 'negative only':
                wave = np.hstack([wz, -wr, wp, -wr[::-1], wz])  # Positive only
            else:
                raise Exception('Unsupported polarity choice')

        Voffset = self.driveOffsetSb.value()
        wave += Voffset

        squidId = str(self.tesCombo.currentText())
        if squidId != 'None':
            squid = Pfl102Remote(self.osr, squidId)
        else:
            squid = None
        self.squid = squid

        self.decimation = int(self.decimateCombo.currentText())
        self.x = iterativeDecimate(wave, self.decimation)

        deviceName = str(self.deviceCombo.currentText())
        aoChannel = str(self.aoChannelCombo.currentText())
        aiChannel = str(self.aiChannelCombo.currentText())
        aiTerminalConfig = self.terminalConfiguration()
        aiRange = self.aiRanges[self.aiRangeCombo.currentIndex()]
        aoRange = self.aoRanges[self.aoRangeCombo.currentIndex()]

        s = QSettings('WiscXrayAstro', application='ADR3RunInfo')
        path = str(s.value('runPath', '', type=str))
        fileName = path + '/IV/%s_%s.h5' % (self.sampleLe.text(),
                                            time.strftime('%Y%m%d_%H%M%S'))
        self._fileName = fileName
        hdfFile = hdf.File(fileName, mode='w')
        hdfFile.attrs['Program'] = ApplicationName
        hdfFile.attrs['Version'] = Version
        hdfFile.attrs[
            'Decimation'] = 'Iterative decimate using customized scipy code with filtfilt.'
        hdfFile.attrs['Sample'] = str(self.sampleLe.text())
        hdfFile.attrs['Comment'] = str(self.commentLe.text())
        t = time.time()
        hdfFile.attrs['StartTime'] = t
        hdfFile.attrs['StartTimeLocal'] = time.strftime(
            '%Y-%m-%d %H:%M:%S', time.localtime(t))
        hdfFile.attrs['StartTimeUTC'] = time.strftime('%Y-%m-%d %H:%M:%SZ',
                                                      time.gmtime(t))
        hdfFile.attrs['Voffset'] = Voffset
        hdfFile.attrs['Vmax'] = Vmax
        hdfFile.attrs['sampleRate'] = f
        hdfFile.attrs['decimation'] = self.decimation
        hdfFile.attrs['deviceName'] = deviceName
        hdfFile.attrs['aoChannel'] = aoChannel
        hdfFile.attrs['aoRangeMin'] = aoRange.min
        hdfFile.attrs['aoRangeMax'] = aoRange.max
        hdfFile.attrs['aiChannel'] = aiChannel
        hdfFile.attrs['aiRangeMin'] = aiRange.min
        hdfFile.attrs['aiRangeMax'] = aiRange.max
        hdfFile.attrs['aiTerminalConfig'] = str(
            self.aiTerminalConfigCombo.currentText())
        hdfFile.attrs['zeroHoldTime'] = self.zeroHoldTimeSb.value()
        hdfFile.attrs['peakHoldTime'] = self.peakHoldTimeSb.value()
        hdfFile.attrs['betweenHoldTime'] = self.betweenHoldTimeSb.value()
        hdfFile.attrs['slewRate'] = self.slewRateSb.value()
        hdfFile.attrs['polarity'] = str(polarity)
        hdfFile.attrs['resetPflEverySweep'] = bool(self.pflResetCb.isChecked())

        if squid is not None:
            hdfFile.attrs['pflReport'] = str(squid.report())
            hdfFile.attrs['pflRfb'] = squid.feedbackR()
            hdfFile.attrs['pflCfb'] = squid.feedbackC()

        if self.auxAoRamper is not None:
            hdfFile.attrs['auxAoChannel'] = str(self.auxAoRamper.channel)
            auxAoRange = self.aoRanges[self.auxAoRangeCombo.currentIndex()]
            hdfFile.attrs['auxAoRangeMin'] = auxAoRange.min
            hdfFile.attrs['auxAoRangeMax'] = auxAoRange.max
            hdfFile.attrs['auxAoValue'] = self.auxAoSb.value()

        ds = hdfFile.create_dataset('excitationWave',
                                    data=wave,
                                    compression='lzf',
                                    shuffle=True,
                                    fletcher32=True)
        ds.attrs['units'] = 'V'
        ds = hdfFile.create_dataset('excitationWave_decimated',
                                    data=self.x,
                                    compression='lzf',
                                    shuffle=True,
                                    fletcher32=True)
        ds.attrs['units'] = 'V'

        g = hdfFile.create_group('HK')
        self.hkLogger = HkLogger(
            g, self.hkSub
        )  # Should remove stuff below soon - only kept for backwards compatibility
        self.dsTimeStamps = hdfFile.create_dataset('AdrResistance_TimeStamps',
                                                   (0, ),
                                                   maxshape=(None, ),
                                                   chunks=(500, ),
                                                   dtype=np.float64)
        self.dsTimeStamps.attrs['units'] = 's'
        self.dsAdrResistance = hdfFile.create_dataset('AdrResistance', (0, ),
                                                      maxshape=(None, ),
                                                      chunks=(500, ),
                                                      dtype=np.float64)
        self.dsAdrResistance.attrs['units'] = 'Ohms'
        self.hdfFile = hdfFile

        thread = DaqThread(deviceName,
                           aoChannel,
                           aoRange,
                           aiChannel,
                           aiRange,
                           aiTerminalConfig,
                           parent=self)
        thread.setWave(wave)
        thread.setSampleRate(f)
        thread.dataReady.connect(self.collectData)
        thread.setAuxAoRamper(self.auxAoRamper)
        thread.updateAoVoltage(self.auxAoSb.value())

        if self.recordDriveCb.isChecked():
            aiDriveChannel = str(self.aiDriveChannelCombo.currentText())
            hdfFile.attrs['aiDriveChannel'] = aiDriveChannel
            thread.enableDriveRecording(aiDriveChannel)
            thread.driveDataReady.connect(self.collectDriveData)

        if self.pflResetCb.isChecked():
            thread.setSquid(squid)
        thread.error.connect(self.reportError)
        self.enableWidgets(False)
        self.thread = thread
        self.t0 = None

        #nCollected = gc.collect()
        #print('Garbarge collection before measurement:', nCollected)
        #gc.disable()

        thread.start()
        thread.finished.connect(self.threadFinished)
        #print guppyH.heap()

    def reportError(self, message):
        message = str(message)
        self.logger.error('Exception encountered: %s', message)
        from Utility.Gmail import sendMessage
        try:
            sendMessage(['*****@*****.**'], 'IvCurveDaq error',
                        message)
        except Exception as e:
            self.logger.error('Unable to send email: %s', str(e))
        QMessageBox.critical(self, 'Exception encountered!', message)

    def stopMeasurement(self):
        if self.thread is None:
            return
        if self.stopPb.text() == 'Stop':
            self.thread.stop()
            self.stopPb.setText('Abort')
        else:
            self.thread.abort()

    def threadFinished(self):
        print('Finished, cleaning up.')
        del self.hkLogger
        self.hkLogger = None
        del self.thread
        self.thread = None
        self.closeFile()
        del self.squid
        self.squid = None
        del self.dsAdrResistance
        self.dsAdrResistance = None
        del self.dsTimeStamps
        self.dsTimeStamps = None
        del self.x
        self.x = None
        self.stopPb.setText('Stop')
        self.enableWidgets(True)
        print('Done cleaning.')
        nCollected = gc.collect()
        print('Garbarge collection after measurement:', nCollected)
        #gc.enable()

    def closeFile(self):
        if self.hdfFile is not None:
            del self.hkLogger
            self.hkLogger = None
            t = time.time()
            self.hdfFile.attrs['StopTime'] = t
            self.hdfFile.attrs['StopTimeLocal'] = time.strftime(
                '%Y-%m-%d %H:%M:%S', time.localtime(t))
            self.hdfFile.attrs['StopTimeUTC'] = time.strftime(
                '%Y-%m-%d %H:%M:%SZ', time.gmtime(t))
            self.hdfFile.close()
            del self.hdfFile
            self.hdfFile = None

    def enableWidgets(self, enable):
        self.driveGroupBox.setEnabled(enable)
        self.inputGroupBox.setEnabled(enable)
        self.auxAoChannelCombo.setEnabled(enable)
        self.auxAoRangeCombo.setEnabled(enable)
        self.auxAoEnableCb.setEnabled(enable)
        self.startPb.setEnabled(enable)
        self.stopPb.setEnabled(not enable)

    def collectDriveData(self, timeStamp, dt, data):
        ds = self.hdfFile.create_dataset('DriveSignalRaw',
                                         data=data,
                                         compression='lzf',
                                         shuffle=True,
                                         fletcher32=True)
        ds.attrs['units'] = 'V'
        data = iterativeDecimate(data, self.decimation)
        ds = self.hdfFile.create_dataset('DriveSignalDecimated',
                                         data=data,
                                         compression='lzf',
                                         shuffle=True,
                                         fletcher32=True)
        ds.attrs['units'] = 'V'

    def collectData(self, timeStamp, auxAoVoltage, dt, data):
        Tadr = self.temperatureSb.value()
        if self.t0 is None:
            self.t0 = timeStamp
        data = iterativeDecimate(data, self.decimation)

        currentSweep = self.nSweeps
        self.nSweeps += 1
        self.sweepCountSb.setValue(self.nSweeps)
        try:
            grp = self.hdfFile.create_group('Sweep_%06d' % currentSweep)
            grp.attrs['Time'] = timeStamp
            grp.attrs['TimeLocal'] = time.strftime('%Y-%m-%d %H:%M:%S',
                                                   time.localtime(timeStamp))
            grp.attrs['TimeUTC'] = time.strftime('%Y-%m-%d %H:%M:%SZ',
                                                 time.gmtime(timeStamp))
            grp.attrs['Tadr'] = Tadr
            grp.attrs['auxAoValue'] = auxAoVoltage
            ds = grp.create_dataset('Vsquid',
                                    data=data,
                                    compression='lzf',
                                    shuffle=True,
                                    fletcher32=True)
            ds.attrs['units'] = 'V'
        except Exception:
            exceptionString = traceback.format_exc()
            self.reportError(exceptionString)
            self.stopMeasurement()

        if self.enablePlotCb.isChecked():
            self.curves[currentSweep % len(self.curves)].setData(self.x, data)
        else:
            for curve in self.curves:
                curve.setData([], [])