MIES freezes for 10-15s when changing clampMode
Megan Koch reported an issue with https://github.com/AllenInstitute/MIES/pull/2230 where changing the clamp mode takes way too long (10-15s).
I've tried reproducing that with 5b0bbddb9 (tests/Basic: Ensure that we don't get unexpected ZeroMQ messages, 2025-04-11) of branch feature/2230-Add_zeromq_pub_filters_for_TP with an ITC18 and a real MCC. But failed.
See also the following screencast.
https://github.com/user-attachments/assets/bd9feab0-8dd1-489d-850b-f564f8a4ef6c
@t-b
EDIT: These are from running the TP, not the clamp mode switch. I noticed the TP is running about 10X slower than it normally does.
Total time: 50.4178, Time in Function code: 15.4583 (30.7%)
Top function percentages:
Function MIES_TestPulse.ipf TP_GetValuesFromTPStorage: 27%
Function MIES_IVSCC.ipf IVS_SaveExperiment: 20%
Function MIES_TestPulse.ipf TP_AutoFitBaseline: 15%
Function MIES_DAC-Hardware.ipf HW_NI_ReadDigital: 7%
Function MIES_ThreadsafeUtilities.ipf TS_GetNewestFromThreadQueue: 5%
Function MIES_DAC-Hardware.ipf HW_NI_ReadAnalogSingleAndSlow: 4%
Function MIES_DAC-Hardware.ipf HW_NI_WriteAnalogSingleAndSlow: 3%
Annotated Top Functions:
*******************************************************************************************
Function: MIES_TestPulse.ipf TP_GetValuesFromTPStorage; Percent total 27%
*******************************************************************************************
[00]* |Function/WAVE TP_GetValuesFromTPStorage(WAVE TPStorage, variable headstage, string entry, variable numReqEntries, [variable options])
[00] |
[00] | variable i, idx, value, entryLayer, lastValidEntry, numValidEntries, currentAutoTPCycleID, latestAutoTPCycleID
[00] |
[00]* | if(ParamIsDefault(options))
[00]* | options = TP_GETVALUES_DEFAULT
[00] | else
[00]* | ASSERT(options == TP_GETVALUES_DEFAULT || options == TP_GETVALUES_LATEST_AUTOTPCYCLE, "Invalid option")
[00] | endif
[00] |
[00] | // NOTE_INDEX gives the next free index and therefore also the number of valid entries
[00]* | numValidEntries = GetNumberFromWaveNote(TPStorage, NOTE_INDEX)
[00] |
[00]* | if(numValidEntries <= 0)
[00]* | return $""
[00]* | endif
[00] |
[00]* | lastValidEntry = numValidEntries - 1
[00] |
[00]* | latestAutoTPCycleID = TPStorage[lastValidEntry][headstage][%autoTPCycleID]
[00] |
[00]* | if(numReqEntries == Inf)
[00] | entryLayer = FindDimLabel(TPstorage, LAYERS, entry)
[00] | ASSERT(entryLayer >= 0, "Invalid entry")
[00] | Duplicate/FREE/RMD=[0, lastValidEntry][headstage][entryLayer] TPStorage, slice
[00] | Redimension/N=(numpnts(slice))/E=1 slice
[00] |
[00] | if(options == TP_GETVALUES_LATEST_AUTOTPCYCLE)
[00] | // filter all entries which don't have the latest ID out
[00] | slice[] = (TPStorage[p][headstage][%autoTPCycleID] == latestAutoTPCycleID) ? slice[p] : NaN
[00] | endif
[00] |
[00]* | return ZapNaNs(slice)
[00]* | endif
[00] |
[00]* | ASSERT(IsInteger(numReqEntries) && numReqEntries > 0, "Number of required entries must be larger than zero")
[00] |
[00]* | if(numReqEntries > numValidEntries)
[00] | return $""
[00]* | endif
[00] |
[00]* | Make/FREE/D/N=(numReqEntries) result = NaN
[00] |
[00] | // take the last finite values
[03]* | for(i = lastValidEntry; i >= 0; i -= 1)
[00]* | if(idx == numReqEntries)
[00]* | break
[00]* | endif
[00] |
[19]** | value = TPStorage[i][headstage][%$entry]
[00] |
[05]* | if(!IsFinite(value))
[00]* | continue
[00]* | endif
[00] |
[00]* | if(options == TP_GETVALUES_LATEST_AUTOTPCYCLE)
[00]* | currentAutoTPCycleID = TPStorage[i][headstage][%autoTPCycleID]
[00] |
[00]* | if(currentAutoTPCycleID != latestAutoTPCycleID)
[00] | continue
[00] | endif
[00]* | endif
[00] |
[00]* | result[idx++] = value
[00]* | endfor
[00] |
[00]* | if(idx == numReqEntries)
[00]* | ASSERT(!IsNaN(Sum(result)), "Expected non-nan sum")
[00]* | return result
[00] | endif
[00] |
[00]* | return $""
[00]* |End
*******************************************************************************************
Function: MIES_IVSCC.ipf IVS_SaveExperiment; Percent total 20%
*******************************************************************************************
[00] |Function IVS_SaveExperiment(string filename)
[00] |
[00] | variable err
[00] |
[00] | AssertOnAndClearRTError()
[00] | try
[20]** | SaveExperiment/C/F={1, "", 2}/P=home as filename + ".pxp"; AbortOnRTE
[00] | catch
[00] | err = ClearRTError()
[00] | ASSERT(0, "Could not save experiment due to code: " + num2istr(err))
[00] | endtry
[00] |End
*******************************************************************************************
Function: MIES_TestPulse.ipf TP_AutoFitBaseline; Percent total 15%
*******************************************************************************************
[00]* |static Function [variable result, variable tau, variable baseline] TP_AutoFitBaseline(WAVE data, variable pulseLengthMS)
[00] |
[00] | variable first, last, firstPnt, lastPnt, totalLength, debugEnabled, fitQuality, referenceThreshold
[00] | variable V_FitQuitReason, V_FitOptions, V_FitError, V_AbortCode
[00] | string msg, win
[00] |
[00]* | ASSERT(IsFloatingPointWave(data), "Expected floating point wave")
[00]* | ASSERT(DimSize(data, COLS) <= 1, "Invalid data dimensions")
[00]* | ASSERT(DimOffset(data, ROWS) == 0, "Invalid dimension offset")
[00]* | ASSERT(pulseLengthMS > 0, "Expected valid pulse length")
[00] |
[00] | totalLength = DimDelta(data, ROWS) * (DimSize(data, ROWS) - 1)
[00] |
[00]* | first = 1 / 4 * totalLength + 1 / 2 * pulseLengthMS
[00]* | last = 3 / 4 * totalLength - 1 / 2 * pulseLengthMS
[00]* | ASSERT(first < last, "Invalid first/last")
[00] |
[00]* | baseline = last - first
[00] |
[00] | first += TP_BASELINE_FITTING_INSET
[00] | last -= TP_BASELINE_FITTING_INSET
[00] |
[00] |#ifdef DEBUGGING_ENABLED
[00] | if(DP_DebuggingEnabledForCaller())
[00] | debugEnabled = 1
[00] |
[00] | Duplicate/O data, root:AutoTPDebuggingData/WAVE=displayedData
[00] | Duplicate/O data, root:Res_AutoTPDebuggingData/WAVE=residuals
[00] |
[00] | if(!WindowExists("AutoTPDebugging"))
[00] | Display/K=1/N=AutoTPDebugging displayedData
[00] |
[00] | AppendToGraph/W=AutoTPDebugging/L=res residuals
[00] | AppendToGraph/W=AutoTPDebugging displayedData
[00] | ModifyGraph/W=AutoTPDebugging rgb(Res_AutoTPDebuggingData)=(0, 0, 0), rgb(AutoTPDebuggingData)=(655355, 0, 0)
[00] | ModifyGraph axisEnab(left)={0, 0.65}, axisEnab(res)={0.7, 1}, freePos(res)=0
[00] | endif
[00] |
[00] | Cursor/W=AutoTPDebugging A, $NameOfWave(displayedData), first
[00] | Cursor/W=AutoTPDebugging B, $NameOfWave(displayedData), last
[00] |
[00] | WAVE data = root:AutoTPDebuggingData
[00] | WAVE residuals = root:Res_AutoTPDebuggingData
[00] | endif
[00] |#endif // DEBUGGING_ENABLED
[00] |
[00]* | if(!debugEnabled)
[00]* | Duplicate/FREE data, residuals
[00] | endif
[00] |
[01]* | residuals = NaN
[00] |
[00]* | Make/FREE/D/N=3 coefWave
[00] |
[00] | V_FitOptions = 4
[00] |
[00]* | AssertOnAndClearRTError()
[00] | try
[00] | V_FitError = 0
[00] | V_AbortCode = 0
[00] |
[00]* | firstPnt = ScaleToIndex(data, first, ROWS)
[00]* | lastPnt = ScaleToIndex(data, last, ROWS)
[13]* | CurveFit/Q=(!debugEnabled)/N=(!debugEnabled)/NTHR=1/M=0/W=2 exp_XOffset, kwCWave=coefWave, data[firstPnt, lastPnt]/A=(debugEnabled)/R=residuals; AbortOnRTE
[00]* | catch
[00] | msg = GetRTErrMessage()
[00] | ClearRTError()
[00] |
[00] | ASSERT(0, "CurveFit failed with error: " + msg)
[00] | endtry
[00] |
[00]* | MakeWaveFree($"W_Sigma")
[00]* | MakeWaveFree($"W_FitConstants")
[00] |
[00]* | sprintf msg, "Fit result: tau %g, V_FitError %g, V_FitQuitReason %g\r", coefWave[2], V_FitError, V_FitQuitReason
[00]* | DEBUGPRINT(msg)
[00] |
[00]* | if(V_FitError || V_FitQuitReason)
[00] | return [TP_BASELINE_FIT_RESULT_ERROR, NaN, baseline]
[00] | endif
[00] |
[00] | // @todo check coefficient sign, range, etc
[00] |
[00] | // detect residuals being too large
[00]* | Multithread residuals = residuals[p]^2
[00]* | fitQuality = Sum(residuals, first, last) / (lastPnt - firstPnt)
[00]* | referenceThreshold = 0.25 * abs(WaveMax(data, first, last))
[00] |
[00]* | sprintf msg, "fitQuality %g, referenceThreshold %g\r", fitQuality, referenceThreshold
[00]* | DEBUGPRINT(msg)
[00] |
[00]* | ASSERT(IsFinite(fitQuality), "Invalid fit quality")
[00] |
[00]* | if(fitQuality > referenceThreshold)
[00]* | return [TP_BASELINE_FIT_RESULT_TOO_NOISY, NaN, baseline]
[00] | endif
[00] |
[00]* | return [TP_BASELINE_FIT_RESULT_OK, coefWave[2], baseline]
[00]* |End
*******************************************************************************************
Function: MIES_DAC-Hardware.ipf HW_NI_ReadDigital; Percent total 07%
*******************************************************************************************
[00]* |Function HW_NI_ReadDigital(string device, [variable DIOPort, variable DIOLine, variable flags])
[00] |
[00] | variable taskID, ret, result, lineGrouping
[00] | string line
[00] |
[00]* | DEBUGPRINTSTACKINFO()
[00] |
[00]* | if(ParamIsDefault(DIOPort))
[00]* | DIOPort = 0
[00] | endif
[00] |
[00]* | if(ParamIsDefault(DIOLine))
[00] | sprintf line, "/%s/port%d", device, DIOPort
[00]* | lineGrouping = 0
[00] | else
[00]* | lineGrouping = 1
[02]* | ASSERT(DIOline <= fDAQmx_DIO_PortWidth(device, DIOport), "Line does not exist in port")
[00]* | sprintf line, "/%s/port%d/line%d", device, DIOPort, DIOline
[00]* | endif
[00] |
[00]* | AssertOnAndClearRTError()
[04]* | DAQmx_DIO_Config/DEV=device/DIR=1/LGRP=(lineGrouping) line
[00] |
[00]* | if(ClearRTError())
[00] | print fDAQmx_ErrorString()
[00] | ControlWindowToFront()
[00] | if(flags & HARDWARE_ABORT_ON_ERROR)
[00] | ASSERT(0, "Error calling DAQmx_DIO_Config")
[00] | endif
[00]* | return NaN
[00]* | endif
[00] |
[00]* | taskID = V_DAQmx_DIO_TaskNumber
[00] |
[01]* | result = fDAQmx_DIO_Read(device, taskID)
[00] |
[01]* | ret = fDAQmx_DIO_Finished(device, taskID)
[00]* | if(ret)
[00] | print fDAQmx_ErrorString()
[00] | printf "Error %d: fDAQmx_DIO_Finished\r", ret
[00] | ControlWindowToFront()
[00] | if(flags & HARDWARE_ABORT_ON_ERROR)
[00] | ASSERT(0, "Error calling fDAQmx_DIO_Finished")
[00]* | endif
[00] | endif
[00] |
[00]* | return result
[00]* |End
*******************************************************************************************
Function: MIES_ThreadsafeUtilities.ipf TS_GetNewestFromThreadQueue; Percent total 05%
*******************************************************************************************
[00]* |Function TS_GetNewestFromThreadQueue(variable tgID, string varName, [variable timeout_default, variable timeout_tries])
[00] |
[00] | variable var, err, i
[00] |
[00]* | ASSERT_TS(!isEmpty(varName), "varName must not be empty")
[00] |
[00]* | if(IsNaN(tgID))
[00]* | return NaN
[00]* | endif
[00] |
[00]* | if(ParamIsDefault(timeout_default))
[00]* | timeout_default = NaN
[00]* | endif
[00] |
[00]* | if(ParamIsDefault(timeout_tries))
[00]* | timeout_tries = Inf
[00] | else
[00]* | ASSERT(IsInteger(timeout_tries) && timeout_tries > 0, "Invalid timeout_tries")
[00] | endif
[00] |
[00] | var = NaN
[00] |
[00]* | for(i = 0; i < timeout_tries; i += 1)
[00]* | AssertOnAndClearRTError()
[05]* | DFREF dfr = ThreadGroupGetDFR(tgID, TS_GET_REPEAT_TIMEOUT_IN_MS); err = GetRTError(1)
[00] |
[00]* | if(err)
[00] | ASSERT(err == TS_ERROR_INVALID_TGID, "Unexpected error value of " + num2str(err))
[00]* | return NaN
[00]* | endif
[00] |
[00]* | if(!DataFolderRefStatus(dfr))
[00]* | if(IsFinite(var))
[00]* | return var
[00]* | elseif(TS_ThreadGroupFinished(tgID))
[00]* | return NaN
[00] | else
[00]* | continue
[00]* | endif
[00] | endif
[00] |
[00]* | NVAR/Z/SDFR=dfr var_thread = $varName
[00] |
[00]* | ASSERT_TS(NVAR_Exists(var_thread), "Expected variable from thread does not exist: " + varName)
[00] |
[00] | // overwrite old values
[00]* | var = var_thread
[00] | endfor
[00] |
[00] | return timeout_default
[00]* |End
*******************************************************************************************
Function: MIES_DAC-Hardware.ipf HW_NI_ReadAnalogSingleAndSlow; Percent total 04%
*******************************************************************************************
[00]* |Function HW_NI_ReadAnalogSingleAndSlow(string device, variable channel, [variable flags])
[00] |
[00] | variable value
[00] |
[00] | DEBUGPRINTSTACKINFO()
[00] |
[04]* | value = fDAQmx_ReadChan(device, channel, HW_NI_MIN_VOLTAGE, HW_NI_MAX_VOLTAGE, HW_NI_DIFFERENTIAL_SETUP)
[00] |
[00]* | if(!IsFinite(value))
[00] | if(flags & HARDWARE_ABORT_ON_ERROR)
[00] | ASSERT(0, "Error " + fDAQmx_ErrorString())
[00] | else
[00] | DEBUGPRINT("Error: ", str = fDAQmx_ErrorString())
[00]* | endif
[00] | endif
[00] |
[00]* | return value
[00]* |End
*******************************************************************************************
Function: MIES_DAC-Hardware.ipf HW_NI_WriteAnalogSingleAndSlow; Percent total 03%
*******************************************************************************************
[00]* |Function HW_NI_WriteAnalogSingleAndSlow(string device, variable channel, variable value, [variable flags])
[00] |
[00] | variable ret
[00] |
[00]* | DEBUGPRINTSTACKINFO()
[00] |
[00]* | ASSERT(value < HW_NI_MAX_VOLTAGE && value > HW_NI_MIN_VOLTAGE, "Value to set is out of range")
[03]* | ret = fDAQmx_WriteChan(device, channel, value, HW_NI_MIN_VOLTAGE, HW_NI_MAX_VOLTAGE)
[00] |
[00]* | if(ret)
[00] | if(flags & HARDWARE_ABORT_ON_ERROR)
[00] | ASSERT(0, "Error: " + fDAQmx_ErrorString())
[00] | else
[00] | DEBUGPRINT("Error: ", str = fDAQmx_ErrorString())
[00]* | endif
[00]* | endif
[00] |
[00]* | return ret
[00]* |End
@t-b
profiling results with zeromq_stop(), after MIES DA_ephys GUI clamp-mode switch, and TP in MIES was noticeably slow.
Total time: 12.6324, Time in Function code: 0.473828 (3.75%)
Top function percentages:
Function MIES_ThreadsafeUtilities.ipf TS_GetNewestFromThreadQueue: 33%
Function MIES_DAC-Hardware.ipf HW_NI_ReadDigital: 27%
Function MIES_DAC-Hardware.ipf HW_NI_WriteAnalogSingleAndSlow: 9%
Function MIES_Oscilloscope.ipf SCOPE_ITC_UpdateOscilloscope: 4%
Function MIES_Oscilloscope.ipf SCOPE_UpdateGraph: 3%
Function MIES_TestPulse.ipf TP_ROAnalysis: 3%
Function MIES_Oscilloscope.ipf SCOPE_UpdateOscilloscopeData: 2%
Annotated Top Functions:
*******************************************************************************************
Function: MIES_ThreadsafeUtilities.ipf TS_GetNewestFromThreadQueue; Percent total 33%
*******************************************************************************************
[00]* |Function TS_GetNewestFromThreadQueue(variable tgID, string varName, [variable timeout_default, variable timeout_tries])
[00] |
[00] | variable var, err, i
[00] |
[00]* | ASSERT_TS(!isEmpty(varName), "varName must not be empty")
[00] |
[00]* | if(IsNaN(tgID))
[00] | return NaN
[00]* | endif
[00] |
[00]* | if(ParamIsDefault(timeout_default))
[00]* | timeout_default = NaN
[00] | endif
[00] |
[00]* | if(ParamIsDefault(timeout_tries))
[00] | timeout_tries = Inf
[00] | else
[00]* | ASSERT(IsInteger(timeout_tries) && timeout_tries > 0, "Invalid timeout_tries")
[00] | endif
[00] |
[00]* | var = NaN
[00] |
[00]* | for(i = 0; i < timeout_tries; i += 1)
[00]* | AssertOnAndClearRTError()
[33]*** | DFREF dfr = ThreadGroupGetDFR(tgID, TS_GET_REPEAT_TIMEOUT_IN_MS); err = GetRTError(1)
[00] |
[00]* | if(err)
[00] | ASSERT(err == TS_ERROR_INVALID_TGID, "Unexpected error value of " + num2str(err))
[00] | return NaN
[00]* | endif
[00] |
[00]* | if(!DataFolderRefStatus(dfr))
[00]* | if(IsFinite(var))
[00]* | return var
[00] | elseif(TS_ThreadGroupFinished(tgID))
[00] | return NaN
[00] | else
[00] | continue
[00] | endif
[00] | endif
[00] |
[00]* | NVAR/Z/SDFR=dfr var_thread = $varName
[00] |
[00]* | ASSERT_TS(NVAR_Exists(var_thread), "Expected variable from thread does not exist: " + varName)
[00] |
[00] | // overwrite old values
[00] | var = var_thread
[00]* | endfor
[00] |
[00]* | return timeout_default
[00]* |End
*******************************************************************************************
Function: MIES_DAC-Hardware.ipf HW_NI_ReadDigital; Percent total 27%
*******************************************************************************************
[00]* |Function HW_NI_ReadDigital(string device, [variable DIOPort, variable DIOLine, variable flags])
[00] |
[00] | variable taskID, ret, result, lineGrouping
[00] | string line
[00] |
[00] | DEBUGPRINTSTACKINFO()
[00] |
[00]* | if(ParamIsDefault(DIOPort))
[00] | DIOPort = 0
[00] | endif
[00] |
[00] | if(ParamIsDefault(DIOLine))
[00] | sprintf line, "/%s/port%d", device, DIOPort
[00]* | lineGrouping = 0
[00] | else
[00]* | lineGrouping = 1
[06]* | ASSERT(DIOline <= fDAQmx_DIO_PortWidth(device, DIOport), "Line does not exist in port")
[00]* | sprintf line, "/%s/port%d/line%d", device, DIOPort, DIOline
[00] | endif
[00] |
[00]* | AssertOnAndClearRTError()
[13]* | DAQmx_DIO_Config/DEV=device/DIR=1/LGRP=(lineGrouping) line
[00] |
[00]* | if(ClearRTError())
[00] | print fDAQmx_ErrorString()
[00] | ControlWindowToFront()
[00] | if(flags & HARDWARE_ABORT_ON_ERROR)
[00] | ASSERT(0, "Error calling DAQmx_DIO_Config")
[00] | endif
[00]* | return NaN
[00]* | endif
[00] |
[00]* | taskID = V_DAQmx_DIO_TaskNumber
[00] |
[05]* | result = fDAQmx_DIO_Read(device, taskID)
[00] |
[02]* | ret = fDAQmx_DIO_Finished(device, taskID)
[00]* | if(ret)
[00] | print fDAQmx_ErrorString()
[00] | printf "Error %d: fDAQmx_DIO_Finished\r", ret
[00] | ControlWindowToFront()
[00] | if(flags & HARDWARE_ABORT_ON_ERROR)
[00] | ASSERT(0, "Error calling fDAQmx_DIO_Finished")
[00]* | endif
[00] | endif
[00] |
[00]* | return result
[00]* |End
*******************************************************************************************
Function: MIES_DAC-Hardware.ipf HW_NI_WriteAnalogSingleAndSlow; Percent total 09%
*******************************************************************************************
[00]* |Function HW_NI_WriteAnalogSingleAndSlow(string device, variable channel, variable value, [variable flags])
[00] |
[00] | variable ret
[00] |
[00]* | DEBUGPRINTSTACKINFO()
[00] |
[00]* | ASSERT(value < HW_NI_MAX_VOLTAGE && value > HW_NI_MIN_VOLTAGE, "Value to set is out of range")
[09]* | ret = fDAQmx_WriteChan(device, channel, value, HW_NI_MIN_VOLTAGE, HW_NI_MAX_VOLTAGE)
[00] |
[00]* | if(ret)
[00] | if(flags & HARDWARE_ABORT_ON_ERROR)
[00] | ASSERT(0, "Error: " + fDAQmx_ErrorString())
[00] | else
[00] | DEBUGPRINT("Error: ", str = fDAQmx_ErrorString())
[00] | endif
[00] | endif
[00] |
[00]* | return ret
[00]* |End
*******************************************************************************************
Function: MIES_DAC-Hardware.ipf HW_NI_WriteAnalogSingleAndSlow; Percent total 09%
*******************************************************************************************
[00]* |Function HW_NI_WriteAnalogSingleAndSlow(string device, variable channel, variable value, [variable flags])
[00] |
[00] | variable ret
[00] |
[00]* | DEBUGPRINTSTACKINFO()
[00] |
[00]* | ASSERT(value < HW_NI_MAX_VOLTAGE && value > HW_NI_MIN_VOLTAGE, "Value to set is out of range")
[09]* | ret = fDAQmx_WriteChan(device, channel, value, HW_NI_MIN_VOLTAGE, HW_NI_MAX_VOLTAGE)
[00] |
[00]* | if(ret)
[00] | if(flags & HARDWARE_ABORT_ON_ERROR)
[00] | ASSERT(0, "Error: " + fDAQmx_ErrorString())
[00] | else
[00] | DEBUGPRINT("Error: ", str = fDAQmx_ErrorString())
[00] | endif
[00] | endif
[00] |
[00]* | return ret
[00]* |End
*******************************************************************************************
Function: MIES_Oscilloscope.ipf SCOPE_ITC_UpdateOscilloscope; Percent total 04%
*******************************************************************************************
[00]* |static Function SCOPE_ITC_UpdateOscilloscope(string device, variable dataAcqOrTP, variable chunk, variable fifoPos)
[00] |
[00] | WAVE OscilloscopeData = GetOscilloscopeWave(device)
[00] | variable length, first, last
[00] | variable startOfADColumns, endOfADColumns, decMethod, decFactor, i
[00] | string msg
[00]* | WAVE/WAVE scaledDataWave = GetScaledDataWave(device)
[00] | WAVE DAQDataWave = GetDAQDataWave(device, dataAcqOrTP)
[00] | WAVE DAQConfigWave = GetDAQConfigWave(device)
[00]* | WAVE ADCs = GetADCListFromConfig(DAQConfigWave)
[00]* | WAVE DACs = GetDACListFromConfig(DAQConfigWave)
[00] | startOfADColumns = DimSize(DACs, ROWS)
[00]* | endOfADColumns = startOfADColumns + DimSize(ADCs, ROWS)
[00] |
[00]* | WAVE allGain = SWS_GETChannelGains(device, timing = GAIN_AFTER_DAQ)
[00] |
[00] | if(dataAcqOrTP == TEST_PULSE_MODE)
[00]* | WAVE TPSettingsCalc = GetTPSettingsCalculated(device)
[00]* | length = TPSettingsCalc[%totalLengthPointsTP_ADC]
[00] | first = chunk * length
[00]* | last = first + length - 1
[00]* | ASSERT(first >= 0 && last < DimSize(DAQDataWave, ROWS) && first < last, "Invalid wave subrange")
[00] |
[00] |#ifdef DEBUGGING_ENABLED
[00] | if(DP_DebuggingEnabledForCaller())
[00] |
[00] | DAQDataWave[0][0] += 0
[00] | if(!WindowExists("DAQDataWaveTPMD"))
[00] | Display/N=DAQDataWaveTPMD DAQDataWave[][1]
[00] | endif
[00] |
[00] | Cursor/W=DAQDataWaveTPMD/H=2/P A, $NameOfWave(DAQDataWave), first
[00] | Cursor/W=DAQDataWaveTPMD/H=2/P B, $NameOfWave(DAQDataWave), last
[00] | endif
[00] |#endif // DEBUGGING_ENABLED
[00] |
[03]* | Multithread OscilloscopeData[][startOfADColumns, endOfADColumns - 1] = DAQDataWave[first + p][q] / allGain[q]
[00]* | for(i = startOfADColumns; i < endOfADColumns; i += 1)
[00]* | WAVE scaledChannel = scaledDataWave[i]
[01]* | Multithread scaledChannel[] = OscilloscopeData[p][i]
[00] | endfor
[00] |
[00]* | Make/FREE/N=(DimSize(ADCs, ROWS)) tpColumns
[00]* | tpColumns[] = startOfADColumns + p
[00] | SCOPE_UpdatePowerSpectrum(device, tpColumns)
[00] |
[00] | elseif(dataAcqOrTP == DATA_ACQUISITION_MODE)
[00] |
[00] | if(fifopos <= 0)
[00] | return NaN
[00] | endif
[00] |
[00] | NVAR fifoPosGlobal = $GetFifoPosition(device)
[00] |
[00] | if(fifoPosGlobal == fifoPos)
[00] | return NaN
[00] | endif
[00] |
[00] | AssertOnAndClearRTError()
[00] | try
[00] | for(i = startOfADColumns; i < endOfADColumns; i += 1)
[00] | WAVE scaledChannel = scaledDataWave[i]
[00] | Multithread scaledChannel[fifoPosGlobal, fifoPos - 1] = DAQDataWave[p][i] / allGain[i]; AbortOnRTE
[00] | endfor
[00] | catch
[00] | sprintf msg, "Writing scaledDataWave failed, please save the experiment and file a bug report: fifoPosGlobal %g, fifoPos %g, Channel Index %d, scaledChannelWave rows %g, stopCollectionPoint %g\r", fifoPosGlobal, fifoPos, i, DimSize(scaledChannel, ROWS), ROVAR(GetStopCollectionPoint(device))
[00] | ASSERT(0, msg)
[00] | endtry
[00] |
[00] | decMethod = GetNumberFromWaveNote(OscilloscopeData, "DecimationMethod")
[00] | decFactor = GetNumberFromWaveNote(OscilloscopeData, "DecimationFactor")
[00] |
[00] | switch(decMethod)
[00] | case DECIMATION_NONE:
[00] | Multithread OscilloscopeData[fifoPosGlobal, fifoPos - 1][startOfADColumns, endOfADColumns - 1] = DAQDataWave[p][q] / allGain[q]
[00] | break
[00] | default:
[00] | Duplicate/FREE/RMD=[startOfADColumns, endOfADColumns - 1] allGain, gain
[00] | gain[] = 1 / gain[p]
[00] | DecimateWithMethod(DAQDataWave, OscilloscopeData, decFactor, decMethod, firstRowInp = fifoPosGlobal, lastRowInp = fifoPos - 1, firstColInp = startOfADColumns, lastColInp = endOfADColumns - 1, factor = gain)
[00] | endswitch
[00] | else
[00]* | ASSERT(0, "Invalid dataAcqOrTP value")
[00]* | endif
[00] |End
*******************************************************************************************
Function: MIES_Oscilloscope.ipf SCOPE_UpdateGraph; Percent total 03%
*******************************************************************************************
[00]* |Function SCOPE_UpdateGraph(string device, variable dataAcqOrTP)
[00] |
[00] | variable i, numADCs, range, numDACs, statsMin, statsMax
[00] | variable axisMin, axisMax, spacing, additionalSpacing
[00] | variable showSteadyStateResistance, showPeakResistance, showPowerSpectrum
[00] | variable updateInt, now
[00] | string graph, leftAxis
[00] |
[00]* | NVAR timestamp = $GetLastAcqHookCallTimeStamp(device)
[00]* | updateInt = DAG_GetNumericalValue(device, "setvar_Settings_OsciUpdInt")
[00]* | now = DateTime
[00]* | if((now - timestamp) < (updateInt * MILLI_TO_ONE))
[00] | return 0
[00] | endif
[00]* | timestamp = now
[00] |
[00] | graph = SCOPE_GetGraph(device)
[00]* | if(SCOPE_GetTPTopAxisStart(device, axisMin))
[00] | SetAxis/W=$graph $AXIS_SCOPE_TP_TIME, axisMin, axisMin + SCOPE_TIMEAXIS_RESISTANCE_RANGE
[00]* | endif
[00] |
[00]* | if(DAG_GetNumericalValue(device, "Popup_Settings_OsciUpdMode") != GUI_SETTING_OSCI_SCALE_INTERVAL)
[00] | return 0
[00]* | endif
[00] |
[00]* | [showSteadyStateResistance, showPeakResistance, showPowerSpectrum] = SCOPE_GetCheckBoxesForAddons(device, dataAcqOrTP)
[00] |
[00]* | if(showPowerSpectrum)
[00] | return NaN
[00] | endif
[00] |
[00] | if(!GotTPChannelsOnADCs(device))
[00] | return NaN
[00] | endif
[00] |
[00]* | WAVE config = GetDAQConfigWave(device)
[00]* | WAVE ADCmode = GetADCTypesFromConfig(config)
[00]* | WAVE ADCs = GetADCListFromConfig(config)
[00]* | WAVE DACs = GetDACListFromConfig(config)
[00]* | numADCs = DimSize(ADCs, ROWS)
[00]* | numDACs = DimSize(DACs, ROWS)
[00] |
[00]* | if(dataAcqOrTP == DATA_ACQUISITION_MODE)
[00] | WAVE TPData = GetTPOscilloscopeWave(device)
[00] | else
[00]* | WAVE TPData = GetOscilloscopeWave(device)
[00]* | endif
[00] |
[00]* | additionalSpacing = DAG_GetNumericalValue(device, "setvar_Settings_OsciUpdExt") * PERCENT_TO_ONE
[00] |
[00] | // scale the left AD axes
[00]* | for(i = 0; i < numADCs; i += 1)
[00] |
[00]* | if(ADCmode[i] != DAQ_CHANNEL_TYPE_TP)
[00] | continue
[00]* | endif
[00] |
[00]* | leftAxis = AXIS_SCOPE_AD + num2str(ADCs[i])
[00] |
[03]* | WaveStats/M=1/Q/RMD=[][numDACs + i] TPData
[00] |
[00]* | statsMin = V_min
[00]* | statsMax = V_max
[00] |
[00] | // data is propably just zero, skip the axis
[00]* | if(statsMin == statsMax || (IsNaN(statsMin) && IsNaN(statsMax)))
[00] | continue
[00] | endif
[00] |
[00]* | GetAxis/Q/W=$graph $leftAxis
[00]* | ASSERT(!V_Flag, "Expected axis does not exist")
[00] |
[00] | axisMin = V_min
[00] | axisMax = V_max
[00] |
[00]* | if(axisMax == axisMin || (axisMin == -1 && axisMax == 1))
[00] | spacing = (statsMax - statsMin) * additionalSpacing
[00] | else
[00]* | spacing = (axisMax - axisMin) * additionalSpacing
[00] | endif
[00] |
[00]* | if(axisMin < statsMin && abs(statsMin - axisMin) < spacing)
[00]* | if(axisMax > statsMax && abs(statsMax - axisMax) < spacing)
[00] | continue
[00] | endif
[00] | endif
[00] |
[00] | SetAxis/W=$graph $leftAxis, statsMin - spacing / 2.0, statsMax + spacing / 2.0
[00]* | endfor
[00] |End
*******************************************************************************************
Function: MIES_TestPulse.ipf TP_ROAnalysis; Percent total 03%
*******************************************************************************************
[00]* |Function TP_ROAnalysis(STRUCT ASYNC_ReadOutStruct &ar)
[00] |
[00] | variable i, j, bufSize, headstage, marker
[00] | variable posMarker, posAsync
[00] | string lbl
[00] |
[00]* | if(ar.rtErr || ar.abortCode)
[00] | ASSERT(!ar.rtErr, "TP analysis thread encountered RTE " + ar.rtErrMsg)
[00] | ASSERT(!ar.abortCode, "TP analysis thread aborted with code: " + GetErrMessage(ar.abortCode))
[00] | endif
[00] |
[00]* | DFREF dfr = ar.dfr
[00] |
[00]* | WAVE/SDFR=dfr inData = tpData
[00]* | SVAR/SDFR=dfr device = device
[00]* | headstage = inData[%HEADSTAGE]
[00]* | marker = inData[%MARKER]
[00] |
[00]* | WAVE asyncBuffer = GetTPResultAsyncBuffer(device)
[00] |
[00]* | bufSize = DimSize(asyncBuffer, ROWS)
[00]* | posMarker = FindDimLabel(asyncBuffer, LAYERS, "MARKER")
[00]* | posAsync = FindDimLabel(asyncBuffer, COLS, "ASYNCDATA")
[00] |
[00]* | FindValue/RMD=[][posAsync][posMarker, posMarker]/V=(marker)/T=0 asyncBuffer
[00]* | i = (V_Value >= 0) ? V_Row : bufSize
[00] |
[00]* | if(i == bufSize)
[00]* | Redimension/N=(bufSize + 1, -1, -1) asyncBuffer
[00]* | asyncBuffer[bufSize][][] = NaN
[00]* | asyncBuffer[bufSize][posAsync][%REC_CHANNELS] = 0
[00]* | asyncBuffer[bufSize][posAsync][posMarker] = marker
[00] | endif
[00] |
[00]* | WAVE/T dimLabels = ListToTextWave(TP_ANALYSIS_DATA_LABELS, ";")
[00]* | for(lbl : dimLabels)
[00]* | asyncBuffer[i][%$lbl][headstage] = inData[%$lbl]
[00] | endfor
[00]* | asyncBuffer[i][posAsync][%REC_CHANNELS] += 1
[00] |
[00] | // got one set of results ready
[00]* | if(asyncBuffer[i][posAsync][%REC_CHANNELS] == inData[%NUMBER_OF_TP_CHANNELS])
[00] |
[00]* | WAVE TPResults = GetTPResults(device)
[00]* | WAVE TPSettings = GetTPSettings(device)
[00] |
[00]* | MultiThread TPResults[%BaselineSteadyState][] = asyncBuffer[i][%BASELINE][q]
[00]* | MultiThread TPResults[%ResistanceSteadyState][] = asyncBuffer[i][%STEADYSTATERES][q]
[00]* | MultiThread TPResults[%ResistanceInst][] = asyncBuffer[i][%INSTANTRES][q]
[00]* | MultiThread TPResults[%ElevatedSteadyState][] = asyncBuffer[i][%ELEVATED_SS][q]
[00]* | MultiThread TPResults[%ElevatedInst][] = asyncBuffer[i][%ELEVATED_INST][q]
[00]* | MultiThread TPResults[%NOW][] = asyncBuffer[i][%NOW][q]
[00]* | MultiThread TPResults[%HEADSTAGE][] = asyncBuffer[i][%HEADSTAGE][q]
[00]* | MultiThread TPResults[%MARKER][] = asyncBuffer[i][%MARKER][q]
[00]* | MultiThread TPResults[%NUMBER_OF_TP_CHANNELS][] = asyncBuffer[i][%NUMBER_OF_TP_CHANNELS][q]
[00]* | MultiThread TPResults[%TIMESTAMP][] = asyncBuffer[i][%TIMESTAMP][q]
[00]* | MultiThread TPResults[%TIMESTAMPUTC][] = asyncBuffer[i][%TIMESTAMPUTC][q]
[00]* | MultiThread TPResults[%CLAMPMODE][] = asyncBuffer[i][%CLAMPMODE][q]
[00]* | MultiThread TPResults[%CLAMPAMP][] = asyncBuffer[i][%CLAMPAMP][q]
[00]* | MultiThread TPResults[%BASELINEFRAC][] = asyncBuffer[i][%BASELINEFRAC][q]
[00]* | MultiThread TPResults[%CYCLEID][] = asyncBuffer[i][%CYCLEID][q]
[00]* | MultiThread TPResults[%TPLENGTHPOINTSADC][] = asyncBuffer[i][%TPLENGTHPOINTSADC][q]
[00]* | MultiThread TPResults[%PULSELENGTHPOINTSADC][] = asyncBuffer[i][%PULSELENGTHPOINTSADC][q]
[00]* | MultiThread TPResults[%PULSESTARTPOINTSADC][] = asyncBuffer[i][%PULSESTARTPOINTSADC][q]
[00]* | MultiThread TPResults[%SAMPLINGINTERVALADC][] = asyncBuffer[i][%SAMPLINGINTERVALADC][q]
[00]* | MultiThread TPResults[%TPLENGTHPOINTSDAC][] = asyncBuffer[i][%TPLENGTHPOINTSDAC][q]
[00]* | MultiThread TPResults[%PULSELENGTHPOINTSDAC][] = asyncBuffer[i][%PULSELENGTHPOINTSDAC][q]
[00]* | MultiThread TPResults[%PULSESTARTPOINTSDAC][] = asyncBuffer[i][%PULSESTARTPOINTSDAC][q]
[00]* | MultiThread TPResults[%SAMPLINGINTERVALDAC][] = asyncBuffer[i][%SAMPLINGINTERVALDAC][q]
[00] |
[00] | // Remove finished results from buffer
[00]* | DeletePoints i, 1, asyncBuffer
[00] | if(!DimSize(asyncBuffer, ROWS))
[00]* | KillOrMoveToTrash(wv = asyncBuffer)
[00] | endif
[00] |
[00]* | if(TPSettings[%bufferSize][INDEP_HEADSTAGE] > 1)
[00] | WAVE TPResultsBuffer = GetTPResultsBuffer(device)
[00] | TP_CalculateAverage(TPResultsBuffer, TPResults)
[00]* | endif
[00] |
[00]* | TPResults[%AutoTPAmplitude][] = NaN
[00]* | TPResults[%AutoTPBaseline][] = NaN
[00]* | TPResults[%AutoTPBaselineRangeExceeded][] = NaN
[00]* | TPResults[%AutoTPBaselineFitResult][] = NaN
[00] |
[00]* | MultiThread TPResults[%AutoTPDeltaV][] = TPResults[%ElevatedSteadyState][q] - TPResults[%BaselineSteadyState][q]
[00] |
[00]* | TP_AutoAmplitudeAndBaseline(device, TPResults, marker)
[00]* | DQ_ApplyAutoBias(device, TPResults)
[00]* | TP_RecordTP(device, TPResults, inData[%NOW])
[00]* | endif
[00] |End
*******************************************************************************************
Function: MIES_Oscilloscope.ipf SCOPE_UpdateOscilloscopeData; Percent total 02%
*******************************************************************************************
[00]* |Function SCOPE_UpdateOscilloscopeData(string device, variable dataAcqOrTP, [variable chunk, variable fifoPos, variable deviceID])
[00] |
[00] | STRUCT TPAnalysisInput tpInput
[00] | variable i, j
[00] | variable tpChannels, numADCs, numDACs, tpLengthPointsADC, tpStart, tpEnd, tpStartPos
[00] | variable TPChanIndex, saveTP, clampAmp
[00] | variable headstage, fifoLatest, channelIndex
[00] | string hsList
[00] |
[00]* | variable hardwareType = GetHardwareType(device)
[00]* | switch(hardwareType)
[00] | case HARDWARE_ITC_DAC:
[00]* | if(dataAcqOrTP == TEST_PULSE_MODE)
[00] | if(ParamIsDefault(chunk))
[00] | chunk = 0
[00] | endif
[00]* | ASSERT(ParamIsDefault(fifoPos), "optional parameter fifoPos is not possible with TEST_PULSE_MODE")
[00] | elseif(dataAcqOrTP == DATA_ACQUISITION_MODE)
[00] | ASSERT(!ParamIsDefault(fifoPos), "optional parameter fifoPos missing")
[00] | ASSERT(ParamIsDefault(chunk), "optional parameter chunk is not possible with DATA_ACQUISITION_MODE")
[00] | fifopos = SCOPE_ITC_AdjustFIFOPos(device, fifopos)
[00]* | ASSERT(IsFinite(fifopos), "Invalid fifo position")
[00] | endif
[00]* | SCOPE_ITC_UpdateOscilloscope(device, dataAcqOrTP, chunk, fifoPos)
[00]* | break
[00] | case HARDWARE_NI_DAC:
[00] | ASSERT(!ParamIsDefault(deviceID), "optional parameter deviceID missing (required for NI devices in TP mode)")
[00] | SCOPE_NI_UpdateOscilloscope(device, dataAcqOrTP, deviceID, fifoPos)
[00] | break
[00] | case HARDWARE_SUTTER_DAC:
[00] | if(dataAcqOrTP == TEST_PULSE_MODE)
[00] | ASSERT(!ParamIsDefault(chunk), "optional parameter chunk is missing with TEST_PULSE_MODE")
[00] | ASSERT(ParamIsDefault(fifoPos), "optional parameter fifoPos is not possible with TEST_PULSE_MODE")
[00] | elseif(dataAcqOrTP == DATA_ACQUISITION_MODE)
[00] | ASSERT(!ParamIsDefault(fifoPos), "optional parameter fifoPos missing")
[00] | ASSERT(ParamIsDefault(chunk), "optional parameter chunk is not possible with DATA_ACQUISITION_MODE")
[00] | endif
[00] | SCOPE_SU_UpdateOscilloscope(device, dataAcqOrTP, chunk, fifoPos)
[00] | break
[00] | default:
[00]* | ASSERT(0, "Unsupported hardware type")
[00] | endswitch
[00] |
[00]* | WAVE config = GetDAQConfigWave(device)
[00] | WAVE ADCmode = GetADCTypesFromConfig(config)
[00]* | tpChannels = GetNrOfTypedChannels(ADCmode, DAQ_CHANNEL_TYPE_TP)
[00] |
[00] | // send data to TP Analysis if TP present
[00]* | NVAR fifoPosGlobal = $GetFifoPosition(device)
[00] |
[00]* | if(tpChannels)
[00] | saveTP = DAG_GetNumericalValue(device, "check_Settings_TP_SaveTP")
[00] | WAVE TPSettings = GetTPSettings(device)
[00]* | WAVE TPSettingsCalc = GetTPSettingsCalculated(device)
[00] |
[00]* | tpLengthPointsADC = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%totalLengthPointsTP_ADC] : TPSettingsCalc[%totalLengthPointsDAQ_ADC]
[00] |
[00] | // use a 'virtual' end position for fifoLatest for TP Mode since the input data contains one TP only
[00]* | fifoLatest = (dataAcqOrTP == TEST_PULSE_MODE) ? tpLengthPointsADC : fifoPos
[00] |
[00]* | WAVE ADCs = GetADCListFromConfig(config)
[00]* | WAVE DACs = GetDACListFromConfig(config)
[00]* | WAVE hsProp = GetHSProperties(device)
[00] |
[00]* | WAVE/WAVE scaledDataWave = GetScaledDataWave(device)
[00]* | numDACs = DimSize(DACs, ROWS)
[00] | numADCs = DimSize(ADCs, ROWS)
[00] |
[00] | // note: currently this works for multiplier = 1 only, see DC_PlaceDataInDAQDataWave
[00]* | Make/FREE/N=(tpLengthPointsADC) channelData
[00]* | WAVE tpInput.data = channelData
[00] |
[00]* | tpInput.device = device
[00]* | tpInput.tpLengthPointsADC = tpLengthPointsADC
[00]* | tpInput.pulseLengthPointsADC = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%pulseLengthPointsTP_ADC] : TPSettingsCalc[%pulseLengthPointsDAQ_ADC]
[00]* | tpInput.pulseStartPointsADC = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%pulseStartPointsTP_ADC] : TPSettingsCalc[%pulseStartPointsDAQ_ADC]
[00]* | tpInput.samplingIntervalADC = DimDelta(scaledDataWave[numDACs], ROWS)
[00]* | tpInput.tpLengthPointsDAC = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%totalLengthPointsTP] : TPSettingsCalc[%totalLengthPointsDAQ]
[00]* | tpInput.pulseLengthPointsDAC = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%pulseLengthPointsTP] : TPSettingsCalc[%pulseLengthPointsDAQ]
[00]* | tpInput.pulseStartPointsDAC = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%pulseStartPointsTP] : TPSettingsCalc[%pulseStartPointsDAQ]
[00]* | tpInput.samplingIntervalDAC = DimDelta(scaledDataWave[0], ROWS)
[00]* | tpInput.baselineFrac = TPSettingsCalc[%baselineFrac]
[00]* | tpInput.readTimeStamp = ticks * TICKS_TO_SECONDS
[00] | tpInput.activeADCs = tpChannels
[00] | tpInput.cycleId = ROVAR(GetTestpulseCycleID(device))
[00] |
[00]* | tpStart = trunc(fifoPosGlobal / tpLengthPointsADC)
[00] | tpEnd = trunc(fifoLatest / tpLengthPointsADC)
[00]* | ASSERT(tpStart <= tpEnd, "New fifopos is smaller than previous fifopos")
[00]* | Make/FREE/D/N=(tpEnd - tpStart) tpMarker
[00]* | NewRandomSeed()
[00]* | tpMarker[] = GetUniqueInteger()
[00] |
[00]* | DEBUGPRINT("tpChannels: ", var = tpChannels)
[00] | DEBUGPRINT("tpLength: ", var = tpLengthPointsADC)
[00] |
[00] | for(i = tpStart; i < tpEnd; i += 1)
[00] |
[00]* | tpInput.measurementMarker = tpMarker[i - tpStart]
[00]* | tpStartPos = i * tpLengthPointsADC
[00] |
[00] | if(saveTP)
[00] | Make/FREE/N=(tpLengthPointsADC, tpChannels) StoreTPWave
[00] | for(j = 0; j < tpChannels; j += 1)
[00] | WAVE scaledChannel = scaledDataWave[numDACs + j]
[00] | Multithread StoreTPWave[][j] = scaledChannel[tpStartPos + p]
[00] | endfor
[00] | CopyScales/P scaledChannel, StoreTPWave
[00] | TPChanIndex = 0
[00]* | hsList = ""
[00] | endif
[00] |
[00] | // Use same time for all headstages
[00]* | tpInput.timeStamp = DateTime
[00]* | tpInput.timeStampUTC = DateTimeInUTC()
[00]* | tpInput.sendTPMessage = 1
[00] |
[00]* | for(j = 0; j < numADCs; j += 1)
[00] | if(ADCmode[j] == DAQ_CHANNEL_TYPE_TP)
[00] |
[00]* | WAVE scaledChannel = scaledDataWave[numDACs + j]
[01]* | MultiThread channelData[] = scaledChannel[tpStartPos + p]
[00]* | CopyScales/P scaledChannel, channelData
[00] |
[00]* | headstage = AFH_GetHeadstageFromADC(device, ADCs[j])
[00]* | if(hsProp[headstage][%ClampMode] == I_CLAMP_MODE)
[00] | clampAmp = TPSettings[%amplitudeIC][headstage]
[00] | else
[00]* | clampAmp = TPSettings[%amplitudeVC][headstage]
[00] | endif
[00] | tpInput.clampAmp = clampAmp
[00]* | tpInput.clampMode = hsProp[headstage][%ClampMode]
[00]* | tpInput.headstage = headstage
[00] |
[00]* | DEBUGPRINT("headstage: ", var = headstage)
[00]* | DEBUGPRINT("channel: ", var = numDACs + j)
[00] |
[00]* | TP_SendToAnalysis(device, tpInput)
[00] |
[00]* | if(saveTP)
[00] | hsList = AddListItem(num2str(headstage), hsList, ",", Inf)
[00] | if(TPChanIndex != j)
[00] | MultiThread StoreTPWave[][TPChanIndex] = channelData[p]
[00] | endif
[00]* | TPChanIndex += 1
[00] | endif
[00] |
[00] | endif
[00] | endfor
[00] |
[00] | if(saveTP)
[00] | DEBUGPRINT("Storing TP with marker: ", var = tpInput.measurementMarker)
[00] | TP_StoreTP(device, StoreTPWave, tpInput.measurementMarker, hsList)
[00] | WaveClear StoreTPWave
[00] | endif
[00] |
[00] | endfor
[00] |
[00] | if(dataAcqOrTP == DATA_ACQUISITION_MODE && tpEnd > tpStart)
[00] | tpStartPos = (tpEnd - 1) * tpLengthPointsADC
[00] | if(DAG_GetNumericalValue(device, "check_settings_show_power"))
[00] | WAVE tpOsciForPowerSpectrum = GetScaledTPTempWave(device)
[00] | Make/FREE/D/N=(numADCs) tpColumns
[00] | j = 0
[00] | for(i = 0; i < numADCs; i += 1)
[00] | if(ADCmode[i] == DAQ_CHANNEL_TYPE_TP)
[00] | channelIndex = numDACs + i
[00] | WAVE scaledChannel = scaledDataWave[channelIndex]
[00] | MultiThread tpOsciForPowerSpectrum[][channelIndex] = scaledChannel[tpStartPos + p]
[00] | tpColumns[j] = channelIndex
[00] | j += 1
[00] | endif
[00] | CopyScales/P scaledChannel, tpOsciForPowerSpectrum
[00] | endfor
[00] | Redimension/N=(j) tpColumns
[00] | SCOPE_UpdatePowerSpectrum(device, tpColumns, osci = tpOsciForPowerSpectrum)
[00] | else
[00] | WAVE TPOscilloscopeData = GetTPOscilloscopeWave(device)
[00] | for(i = 0; i < numADCs; i += 1)
[00] | if(ADCmode[i] == DAQ_CHANNEL_TYPE_TP)
[00] | channelIndex = numDACs + i
[00] | WAVE scaledChannel = scaledDataWave[channelIndex]
[00] | MultiThread TPOscilloscopeData[][channelIndex] = scaledChannel[tpStartPos + p]
[00] | endif
[00] | endfor
[00] | endif
[00] | endif
[00] | endif
[00] |
[00] | // Sync fifo position
[00]* | fifoPosGlobal = fifoPos
[00] |
[00]* | ASYNC_ThreadReadOut()
[00] |End
Notes from live debug session (16th April 2025)
- Could reproduce the slowness but it was not consistent slow
- It was slow with either 5b0bbddb9 (tests/Basic: Ensure that we don't get unexpected ZeroMQ messages, 2025-04-11) (ZeroMQ TP message PR) or 88ffd8766 (Merge pull request #2380 from AllenInstitute/bugfix/2380-sf_make_variable_readonly, 2025-04-05) (Two PRs before)
- Nothing big changed in WSE or ACQ4
As mentioned in a recent one-to-one chat with Tim: We can also try to figure out the reason for the slowness by viewding the diff of the involved applications. For this I would need access to the source code of [ ] WSE/ [x] MIES/ [x] ACQ4 and the exact git revision where the bug does occur and where not.
@t-b I need to be careful to check that the TP slowness reported above isn't due to the %baseline being set to max (49%).
ExecuteScriptText is very slow on these machines (a factor of 7 slower than on my laptop). Reported to WM as #issue 7583.