diff --git a/Packages/MIES/MIES_Constants.ipf b/Packages/MIES/MIES_Constants.ipf index 1c096aabe3..0c8c9c2e6e 100644 --- a/Packages/MIES/MIES_Constants.ipf +++ b/Packages/MIES/MIES_Constants.ipf @@ -2311,3 +2311,10 @@ Constant SUTTER_MAX_MAX_TP_PULSES = 10000 Constant INVALID_SWEEP_NUMBER = -1 StrConstant PERCENT_F_MAX_PREC = "%.15f" + +// If this constant with dimLabels is changed the following functions should be verified: +// +// TP_TSAnalysis +// GetTPResultAsyncBuffer +// GetTPResults (reuses same dimlabels partially) +StrConstant TP_ANALYSIS_DATA_LABELS = "BASELINE;STEADYSTATERES;INSTANTRES;ELEVATED_SS;ELEVATED_INST;NOW;HEADSTAGE;MARKER;NUMBER_OF_TP_CHANNELS;TIMESTAMP;TIMESTAMPUTC;CLAMPMODE;CLAMPAMP;BASELINEFRAC;CYCLEID;TPLENGTHPOINTSADC;PULSELENGTHPOINTSADC;PULSESTARTPOINTSADC;SAMPLINGINTERVALADC;TPLENGTHPOINTSDAC;PULSELENGTHPOINTSDAC;PULSESTARTPOINTSDAC;SAMPLINGINTERVALDAC;" diff --git a/Packages/MIES/MIES_MiesUtilities_Conversion.ipf b/Packages/MIES/MIES_MiesUtilities_Conversion.ipf index 4640ef4839..8c5f4ddc5f 100644 --- a/Packages/MIES/MIES_MiesUtilities_Conversion.ipf +++ b/Packages/MIES/MIES_MiesUtilities_Conversion.ipf @@ -270,3 +270,15 @@ Function MapAnaFuncToConstant(anaFunc) #endif endswitch End + +/// @brief returns the unit string for the AD channel depending in clampmode +Function/S GetADChannelUnit(variable clampMode) + + return SelectString(clampMode == V_CLAMP_MODE, "mV", "pA") +End + +/// @brief returns the unit string for the DA channel depending in clampmode +Function/S GetDAChannelUnit(variable clampMode) + + return SelectString(clampMode == V_CLAMP_MODE, "pA", "mV") +End diff --git a/Packages/MIES/MIES_Oscilloscope.ipf b/Packages/MIES/MIES_Oscilloscope.ipf index 5a564a2b51..3e91a39bfe 100644 --- a/Packages/MIES/MIES_Oscilloscope.ipf +++ b/Packages/MIES/MIES_Oscilloscope.ipf @@ -479,7 +479,7 @@ Function SCOPE_UpdateOscilloscopeData(device, dataAcqOrTP, [chunk, fifoPos, devi STRUCT TPAnalysisInput tpInput variable i, j - variable tpChannels, numADCs, numDACs, tpLengthPoints, tpStart, tpEnd, tpStartPos + variable tpChannels, numADCs, numDACs, tpLengthPointsADC, tpStart, tpEnd, tpStartPos variable TPChanIndex, saveTP, clampAmp variable headstage, fifoLatest, channelIndex string hsList @@ -530,10 +530,10 @@ Function SCOPE_UpdateOscilloscopeData(device, dataAcqOrTP, [chunk, fifoPos, devi WAVE TPSettings = GetTPSettings(device) WAVE TPSettingsCalc = GetTPSettingsCalculated(device) - tpLengthPoints = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%totalLengthPointsTP_ADC] : TPSettingsCalc[%totalLengthPointsDAQ_ADC] + tpLengthPointsADC = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%totalLengthPointsTP_ADC] : TPSettingsCalc[%totalLengthPointsDAQ_ADC] // use a 'virtual' end position for fifoLatest for TP Mode since the input data contains one TP only - fifoLatest = (dataAcqOrTP == TEST_PULSE_MODE) ? tpLengthPoints : fifoPos + fifoLatest = (dataAcqOrTP == TEST_PULSE_MODE) ? tpLengthPointsADC : fifoPos WAVE ADCs = GetADCListFromConfig(config) WAVE DACs = GetDACListFromConfig(config) @@ -544,33 +544,40 @@ Function SCOPE_UpdateOscilloscopeData(device, dataAcqOrTP, [chunk, fifoPos, devi numADCs = DimSize(ADCs, ROWS) // note: currently this works for multiplier = 1 only, see DC_PlaceDataInDAQDataWave - Make/FREE/N=(tpLengthPoints) channelData + Make/FREE/N=(tpLengthPointsADC) channelData WAVE tpInput.data = channelData - tpInput.device = device - tpInput.duration = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%pulseLengthPointsTP_ADC] : TPSettingsCalc[%pulseLengthPointsDAQ_ADC] - tpInput.baselineFrac = TPSettingsCalc[%baselineFrac] - tpInput.tpLengthPoints = tpLengthPoints - tpInput.readTimeStamp = ticks * TICKS_TO_SECONDS - tpInput.activeADCs = tpChannels - - tpStart = trunc(fifoPosGlobal / tpLengthPoints) - tpEnd = trunc(fifoLatest / tpLengthPoints) + tpInput.device = device + tpInput.tpLengthPointsADC = tpLengthPointsADC + tpInput.pulseLengthPointsADC = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%pulseLengthPointsTP_ADC] : TPSettingsCalc[%pulseLengthPointsDAQ_ADC] + tpInput.pulseStartPointsADC = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%pulseStartPointsTP_ADC] : TPSettingsCalc[%pulseStartPointsDAQ_ADC] + tpInput.samplingIntervalADC = DimDelta(scaledDataWave[numDACs], ROWS) + tpInput.tpLengthPointsDAC = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%totalLengthPointsTP] : TPSettingsCalc[%totalLengthPointsDAQ] + tpInput.pulseLengthPointsDAC = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%pulseLengthPointsTP] : TPSettingsCalc[%pulseLengthPointsDAQ] + tpInput.pulseStartPointsDAC = (dataAcqOrTP == TEST_PULSE_MODE) ? TPSettingsCalc[%pulseStartPointsTP] : TPSettingsCalc[%pulseStartPointsDAQ] + tpInput.samplingIntervalDAC = DimDelta(scaledDataWave[0], ROWS) + tpInput.baselineFrac = TPSettingsCalc[%baselineFrac] + tpInput.readTimeStamp = ticks * TICKS_TO_SECONDS + tpInput.activeADCs = tpChannels + tpInput.cycleId = ROVAR(GetTestpulseCycleID(device)) + + tpStart = trunc(fifoPosGlobal / tpLengthPointsADC) + tpEnd = trunc(fifoLatest / tpLengthPointsADC) ASSERT(tpStart <= tpEnd, "New fifopos is smaller than previous fifopos") Make/FREE/D/N=(tpEnd - tpStart) tpMarker NewRandomSeed() tpMarker[] = GetUniqueInteger() DEBUGPRINT("tpChannels: ", var = tpChannels) - DEBUGPRINT("tpLength: ", var = tpLengthPoints) + DEBUGPRINT("tpLength: ", var = tpLengthPointsADC) for(i = tpStart; i < tpEnd; i += 1) tpInput.measurementMarker = tpMarker[i - tpStart] - tpStartPos = i * tpLengthPoints + tpStartPos = i * tpLengthPointsADC if(saveTP) - Make/FREE/N=(tpLengthPoints, tpChannels) StoreTPWave + Make/FREE/N=(tpLengthPointsADC, tpChannels) StoreTPWave for(j = 0; j < tpChannels; j += 1) WAVE scaledChannel = scaledDataWave[numDACs + j] Multithread StoreTPWave[][j] = scaledChannel[tpStartPos + p] @@ -626,7 +633,7 @@ Function SCOPE_UpdateOscilloscopeData(device, dataAcqOrTP, [chunk, fifoPos, devi endfor if(dataAcqOrTP == DATA_ACQUISITION_MODE && tpEnd > tpStart) - tpStartPos = (tpEnd - 1) * tpLengthPoints + tpStartPos = (tpEnd - 1) * tpLengthPointsADC if(DAG_GetNumericalValue(device, "check_settings_show_power")) WAVE tpOsciForPowerSpectrum = GetScaledTPTempWave(device) Make/FREE/D/N=(numADCs) tpColumns diff --git a/Packages/MIES/MIES_Publish.ipf b/Packages/MIES/MIES_Publish.ipf index 150a4940ed..12791e7420 100644 --- a/Packages/MIES/MIES_Publish.ipf +++ b/Packages/MIES/MIES_Publish.ipf @@ -645,3 +645,87 @@ Function PUB_AccessResistanceSmoke(string device, variable sweepNo, variable hea PUB_Publish(jsonID, ANALYSIS_FUNCTION_AR) End + +threadsafe static Function PUB_AddTPResultEntry(variable jsonId, string path, variable value, string unit) + + JSON_AddTreeObject(jsonID, path) + JSON_AddVariable(jsonID, path + "/value", value) + if(!IsEmpty(unit)) + JSON_AddString(jsonID, path + "/unit", unit) + endif +End + +threadsafe Function PUB_TPResult(STRUCT TPZMQData &tpzmq) + + string path + variable jsonId = JSON_New() + string adUnit = GetADChannelUnit(tpzmq.clampMode) + string daUnit = GetDAChannelUnit(tpzmq.clampMode) + + path = "properties" + JSON_AddTreeObject(jsonID, path) + JSON_AddVariable(jsonID, path + "/tp marker", tpzmq.marker) + JSON_AddString(jsonID, path + "/device", tpzmq.device) + JSON_AddVariable(jsonID, path + "/headstage", tpzmq.headstage) + JSON_AddVariable(jsonID, path + "/clamp mode", tpzmq.clampMode) + + PUB_AddTPResultEntry(jsonId, path + "/time of tp acquisition", tpzmq.now, "s") + PUB_AddTPResultEntry(jsonId, path + "/clamp amplitude", tpzmq.clampAmp, daUnit) + PUB_AddTPResultEntry(jsonId, path + "/tp length ADC", tpzmq.tpLengthPointsADC, "points") + PUB_AddTPResultEntry(jsonId, path + "/pulse duration ADC", tpzmq.pulseLengthPointsADC, "points") + PUB_AddTPResultEntry(jsonId, path + "/pulse start point ADC", tpzmq.pulseStartPointsADC, "point") + PUB_AddTPResultEntry(jsonId, path + "/sample interval ADC", tpzmq.samplingIntervalADC, "ms") + PUB_AddTPResultEntry(jsonId, path + "/tp length DAC", tpzmq.tpLengthPointsDAC, "points") + PUB_AddTPResultEntry(jsonId, path + "/pulse duration DAC", tpzmq.pulseLengthPointsDAC, "points") + PUB_AddTPResultEntry(jsonId, path + "/pulse start point DAC", tpzmq.pulseStartPointsDAC, "point") + PUB_AddTPResultEntry(jsonId, path + "/sample interval DAC", tpzmq.samplingIntervalDAC, "ms") + PUB_AddTPResultEntry(jsonId, path + "/baseline fraction", tpzmq.baselineFrac * ONE_TO_PERCENT, "%") + PUB_AddTPResultEntry(jsonId, path + "/timestamp", tpzmq.timeStamp, "s") + PUB_AddTPResultEntry(jsonId, path + "/timestampUTC", tpzmq.timeStampUTC, "s") + PUB_AddTPResultEntry(jsonId, path + "/tp cycle id", tpzmq.cycleId, "") + + path = "results" + JSON_AddTreeObject(jsonID, path) + PUB_AddTPResultEntry(jsonId, path + "/average baseline steady state", tpzmq.avgBaselineSS, adUnit) + PUB_AddTPResultEntry(jsonId, path + "/average tp steady state", tpzmq.avgTPSS, adUnit) + PUB_AddTPResultEntry(jsonId, path + "/instantaneous", tpzmq.instVal, adUnit) + PUB_AddTPResultEntry(jsonId, path + "/steady state resistance", tpzmq.resistanceSS, "MΩ") + PUB_AddTPResultEntry(jsonId, path + "/instantaneous resistance", tpzmq.resistanceInst, "MΩ") + + PUB_Publish(jsonID, ZMQ_FILTER_TPRESULT_NOW, releaseJSON = 0) + if(PUB_CheckPublishingTime(ZMQ_FILTER_TPRESULT_1S, 1)) + PUB_Publish(jsonID, ZMQ_FILTER_TPRESULT_1S, releaseJSON = 0) + endif + if(PUB_CheckPublishingTime(ZMQ_FILTER_TPRESULT_5S, 5)) + PUB_Publish(jsonID, ZMQ_FILTER_TPRESULT_5S, releaseJSON = 0) + endif + if(PUB_CheckPublishingTime(ZMQ_FILTER_TPRESULT_10S, 10)) + PUB_Publish(jsonID, ZMQ_FILTER_TPRESULT_10S, releaseJSON = 0) + endif + JSON_Release(jsonID) +End + +/// @brief Updates the publishing timestamp in the TUFXOP storage and returns 1 if an update is due (0 otherwise) +threadsafe static Function PUB_CheckPublishingTime(string pubFilter, variable period) + + variable curTime + + TUFXOP_AcquireLock/N=(pubFilter) + TUFXOP_GetStorage/Z/Q/N=(pubFilter) lastUpdated + if(V_flag) + TUFXOP_Init/N=(pubFilter) + TUFXOP_GetStorage/Z/N=(pubFilter) lastUpdated + Make/FREE/D dTime = {DateTime} + lastUpdated[0] = dTime + endif + curTime = DateTime + WAVE lastTime = lastUpdated[0] + if(lastTime[0] + period > curTime) + lastTime[0] = curTime + period + TUFXOP_ReleaseLock/N=(pubFilter) + return 1 + endif + TUFXOP_ReleaseLock/N=(pubFilter) + + return 0 +End diff --git a/Packages/MIES/MIES_Structures.ipf b/Packages/MIES/MIES_Structures.ipf index c54b171ac6..4191428936 100644 --- a/Packages/MIES/MIES_Structures.ipf +++ b/Packages/MIES/MIES_Structures.ipf @@ -306,9 +306,15 @@ Structure TPAnalysisInput WAVE data variable clampAmp variable clampMode - variable duration // [points] + variable tpLengthPointsADC + variable pulseLengthPointsADC + variable pulseStartPointsADC + variable samplingIntervalADC + variable tpLengthPointsDAC + variable pulseLengthPointsDAC + variable pulseStartPointsDAC + variable samplingIntervalDAC variable baselineFrac - variable tpLengthPoints variable readTimeStamp variable hsIndex string device @@ -316,6 +322,34 @@ Structure TPAnalysisInput variable activeADCs variable timeStamp variable timeStampUTC + variable cycleId +EndStructure + +/// @brief Helper structure for TP data transfer to zeromq +Structure TPZMQData + variable marker + string device + variable headstage + variable now + variable clampMode + variable clampAmp + variable tpLengthPointsADC + variable pulseLengthPointsADC + variable pulseStartPointsADC + variable samplingIntervalADC + variable tpLengthPointsDAC + variable pulseLengthPointsDAC + variable pulseStartPointsDAC + variable samplingIntervalDAC + variable baselineFrac + variable timeStamp + variable timeStampUTC + variable cycleId + variable avgBaselineSS + variable avgTPSS + variable instVal + variable resistanceSS + variable resistanceInst EndStructure /// @brief Helper structure for GetPlotArea() diff --git a/Packages/MIES/MIES_SweepFormula.ipf b/Packages/MIES/MIES_SweepFormula.ipf index ca07c9b4cf..af5f233194 100644 --- a/Packages/MIES/MIES_SweepFormula.ipf +++ b/Packages/MIES/MIES_SweepFormula.ipf @@ -3027,9 +3027,9 @@ static Function/WAVE SF_OperationTPImpl(string graph, WAVE/WAVE mode, WAVE/Z sel // Assemble TP data WAVE tpInput.data = SF_AverageTPFromSweep(epochMatches, sweepData) - tpInput.tpLengthPoints = DimSize(tpInput.data, ROWS) - tpInput.duration = (str2num(epochTPPulse[0][EPOCH_COL_ENDTIME]) - str2num(epochTPPulse[0][EPOCH_COL_STARTTIME])) * ONE_TO_MILLI / DimDelta(sweepData, ROWS) - tpInput.baselineFrac = TP_CalculateBaselineFraction(tpInput.duration, tpInput.duration + 2 * tpBaseLinePoints) + tpInput.tpLengthPointsADC = DimSize(tpInput.data, ROWS) + tpInput.pulseLengthPointsADC = (str2num(epochTPPulse[0][EPOCH_COL_ENDTIME]) - str2num(epochTPPulse[0][EPOCH_COL_STARTTIME])) * ONE_TO_MILLI / DimDelta(sweepData, ROWS) + tpInput.baselineFrac = TP_CalculateBaselineFraction(tpInput.pulseLengthPointsADC, tpInput.pulseLengthPointsADC + 2 * tpBaseLinePoints) [WAVE settings, settingsIndex] = GetLastSettingChannel(numericalValues, textualValues, sweepNo, CLAMPMODE_ENTRY_KEY, dacChannelNr, XOP_CHANNEL_TYPE_DAC, DATA_ACQUISITION_MODE) SFH_ASSERT(WaveExists(settings), "Failed to retrieve TP Clamp Mode from LBN") diff --git a/Packages/MIES/MIES_TestPulse.ipf b/Packages/MIES/MIES_TestPulse.ipf index 360bc3e102..b3d290e157 100644 --- a/Packages/MIES/MIES_TestPulse.ipf +++ b/Packages/MIES/MIES_TestPulse.ipf @@ -106,45 +106,95 @@ Function TP_StoreTP(device, TPWave, tpMarker, hsList) SetNumberInWaveNote(storedTP, NOTE_INDEX, index) End -/// @brief Return a number of consecutive test pulses ending with the TP -/// identified by tpMarker. -/// -/// The wave reference wave will have as many columns as active headstages were used. -Function/WAVE TP_GetConsecutiveTPsUptoMarker(string device, variable tpMarker, variable number) +static Function TP_GetStoredTPIndex(string device, variable tpMarker) variable numEntries WAVE/WAVE storedTP = GetStoredTestPulseWave(device) numEntries = GetNumberFromWaveNote(storedTP, NOTE_INDEX) - if(numEntries == 0) - return $"" + return NaN endif Make/FREE/N=(numEntries) matches - Multithread matches[0, numEntries - 1] = GetNumberFromWaveNote(storedTP[p], "TPMarker") == tpMarker - FindValue/V=1 matches - if(V_row == -1) + return NaN + endif + + return V_row +End + +Function/WAVE TP_GetStoredTP(string device, variable tpMarker, variable includeDAC) + + variable tpIndex, numEntries, dimMarker, headstage + + includeDAC = !!includeDAC + + tpIndex = TP_GetStoredTPIndex(device, tpMarker) + if(IsNaN(tpIndex)) return $"" endif - Make/FREE/N=(number)/WAVE result + WAVE/WAVE tpStored = GetStoredTestPulseWave(device) + WAVE tpADC = tpStored[tpIndex] + + WAVE tpStorage = GetTPStorage(device) + numEntries = GetNumberFromWaveNote(tpStorage, NOTE_INDEX) + dimMarker = FindDimLabel(tpStorage, LAYERS, "TPMarker") + FindValue/RMD=[][0][dimMarker]/V=(tpMarker) tpStorage + ASSERT(V_row >= 0, "Inconsistent TP data") + Duplicate/FREE/RMD=[V_row][][] tpStorage, tpResult + + if(includeDAC) + for(headstage = 0; headstage < NUM_HEADSTAGES; headstage += 1) + if(!IsNaN(tpResult[0][headstage][%TPLENGTHPOINTSADC])) + break + endif + endfor + Make/FREE/D/N=0 tpDAC + TP_CreateTestPulseWaveImpl(tpDAC, tpResult[0][headstage][%TPLENGTHPOINTSADC][0], tpResult[0][headstage][%PULSESTARTPOINTSADC], tpResult[0][headstage][%PULSELENGTHPOINTSADC]) + tpDAC *= tpResult[0][headstage][%CLAMPAMP] + SetScale/P x, 0, tpResult[0][headstage][%SAMPLINGINTERVALADC], "ms", tpDAC + SetScale d, 0, 0, GetADChannelUnit(tpResult[0][headstage][%ClampMode]), tpDAC + else + WAVE/Z tpDAC = $"" + endif + + Make/FREE/WAVE tpAll = {tpADC, tpDAC, tpResult} + + return tpAll +End + +/// @brief Return a number of consecutive test pulses ending with the TP +/// identified by tpMarker. +/// +/// The wave reference wave will have as many columns as active headstages were used. +Function/WAVE TP_GetConsecutiveTPsUptoMarker(string device, variable tpMarker, variable number) - if(number > V_row + 1) + variable tpIndex, tpCycleId + + tpIndex = TP_GetStoredTPIndex(device, tpMarker) + if(IsNaN(tpIndex)) + return $"" + endif + + if(number > tpIndex + 1) // too few TPs available return $"" endif - result[] = storedTP[V_row - number + 1 + p] + Make/FREE/N=(number)/WAVE result - // check that they all belong to the same TP cycle - Redimension/N=(number) matches - matches[] = GetNumberFromWaveNote(result[0], "TPCycleID") == GetNumberFromWaveNote(result[p], "TPCycleID") + WAVE/WAVE storedTP = GetStoredTestPulseWave(device) + result[] = storedTP[tpIndex - number + 1 + p] - if(Sum(matches) < number) + // check that they all belong to the same TP cycle + Make/FREE/N=(number) matches + tpCycleId = GetNumberFromWaveNote(result[0], "TPCycleID") + matches[] = tpCycleId == GetNumberFromWaveNote(result[p], "TPCycleID") + if(sum(matches) < number) return $"" endif @@ -190,34 +240,24 @@ Function TP_ROAnalysis(dfr, err, errmsg) variable err string errmsg - variable i, j, bufSize - variable posMarker, posAsync, tpBufferSize - variable posBaseline, posSSRes, posInstRes - variable posElevSS, posElevInst + variable i, j, bufSize, headstage, marker + variable posMarker, posAsync + string lbl if(err) ASSERT(0, "RTError " + num2str(err) + " in TP_Analysis thread: " + errmsg) endif - WAVE/SDFR=dfr inData = outData - NVAR/SDFR=dfr now = now - NVAR/SDFR=dfr hsIndex = hsIndex - SVAR/SDFR=dfr device = device - NVAR/SDFR=dfr marker = marker - NVAR/SDFR=dfr activeADCs = activeADCs - NVAR/SDFR=dfr timeStamp = timeStamp - NVAR/SDFR=dfr timeStampUTC = timeStampUTC + WAVE/SDFR=dfr inData = outData + SVAR/SDFR=dfr device = device + headstage = inData[%HEADSTAGE] + marker = inData[%MARKER] WAVE asyncBuffer = GetTPResultAsyncBuffer(device) - bufSize = DimSize(asyncBuffer, ROWS) - posMarker = FindDimLabel(asyncBuffer, LAYERS, "MARKER") - posAsync = FindDimLabel(asyncBuffer, COLS, "ASYNCDATA") - posBaseline = FindDimLabel(asyncBuffer, COLS, "BASELINE") - posSSRes = FindDimLabel(asyncBuffer, COLS, "STEADYSTATERES") - posInstRes = FindDimLabel(asyncBuffer, COLS, "INSTANTRES") - posElevSS = FindDimLabel(asyncBuffer, COLS, "ELEVATED_SS") - posElevInst = FindDimLabel(asyncBuffer, COLS, "ELEVATED_INST") + bufSize = DimSize(asyncBuffer, ROWS) + posMarker = FindDimLabel(asyncBuffer, LAYERS, "MARKER") + posAsync = FindDimLabel(asyncBuffer, COLS, "ASYNCDATA") FindValue/RMD=[][posAsync][posMarker, posMarker]/V=(marker)/T=0 asyncBuffer i = V_Value >= 0 ? V_Row : bufSize @@ -229,26 +269,41 @@ Function TP_ROAnalysis(dfr, err, errmsg) asyncBuffer[bufSize][posAsync][posMarker] = marker endif - asyncBuffer[i][posBaseline][hsIndex] = inData[%BASELINE] - asyncBuffer[i][posSSRes][hsIndex] = inData[%STEADYSTATERES] - asyncBuffer[i][posInstRes][hsIndex] = inData[%INSTANTRES] - asyncBuffer[i][posElevSS][hsIndex] = inData[%ELEVATED_SS] - asyncBuffer[i][posElevInst][hsIndex] = inData[%ELEVATED_INST] - - asyncBuffer[i][posAsync][%NOW] = now + WAVE/T dimLabels = ListToTextWave(TP_ANALYSIS_DATA_LABELS, ";") + for(lbl : dimLabels) + asyncBuffer[i][%$lbl][headstage] = inData[%$lbl] + endfor asyncBuffer[i][posAsync][%REC_CHANNELS] += 1 // got one set of results ready - if(asyncBuffer[i][posAsync][%REC_CHANNELS] == activeADCs) + if(asyncBuffer[i][posAsync][%REC_CHANNELS] == inData[%NUMBER_OF_TP_CHANNELS]) WAVE TPResults = GetTPResults(device) WAVE TPSettings = GetTPSettings(device) - MultiThread TPResults[%BaselineSteadyState][] = asyncBuffer[i][posBaseline][q] - MultiThread TPResults[%ResistanceSteadyState][] = asyncBuffer[i][posSSRes][q] - MultiThread TPResults[%ResistanceInst][] = asyncBuffer[i][posInstRes][q] - MultiThread TPResults[%ElevatedSteadyState][] = asyncBuffer[i][posElevSS][q] - MultiThread TPResults[%ElevatedInst][] = asyncBuffer[i][posElevInst][q] + MultiThread TPResults[%BaselineSteadyState][] = asyncBuffer[i][%BASELINE][q] + MultiThread TPResults[%ResistanceSteadyState][] = asyncBuffer[i][%STEADYSTATERES][q] + MultiThread TPResults[%ResistanceInst][] = asyncBuffer[i][%INSTANTRES][q] + MultiThread TPResults[%ElevatedSteadyState][] = asyncBuffer[i][%ELEVATED_SS][q] + MultiThread TPResults[%ElevatedInst][] = asyncBuffer[i][%ELEVATED_INST][q] + MultiThread TPResults[%NOW][] = asyncBuffer[i][%NOW][q] + MultiThread TPResults[%HEADSTAGE][] = asyncBuffer[i][%HEADSTAGE][q] + MultiThread TPResults[%MARKER][] = asyncBuffer[i][%MARKER][q] + MultiThread TPResults[%NUMBER_OF_TP_CHANNELS][] = asyncBuffer[i][%NUMBER_OF_TP_CHANNELS][q] + MultiThread TPResults[%TIMESTAMP][] = asyncBuffer[i][%TIMESTAMP][q] + MultiThread TPResults[%TIMESTAMPUTC][] = asyncBuffer[i][%TIMESTAMPUTC][q] + MultiThread TPResults[%CLAMPMODE][] = asyncBuffer[i][%CLAMPMODE][q] + MultiThread TPResults[%CLAMPAMP][] = asyncBuffer[i][%CLAMPAMP][q] + MultiThread TPResults[%BASELINEFRAC][] = asyncBuffer[i][%BASELINEFRAC][q] + MultiThread TPResults[%CYCLEID][] = asyncBuffer[i][%CYCLEID][q] + MultiThread TPResults[%TPLENGTHPOINTSADC][] = asyncBuffer[i][%TPLENGTHPOINTSADC][q] + MultiThread TPResults[%PULSELENGTHPOINTSADC][] = asyncBuffer[i][%PULSELENGTHPOINTSADC][q] + MultiThread TPResults[%PULSESTARTPOINTSADC][] = asyncBuffer[i][%PULSESTARTPOINTSADC][q] + MultiThread TPResults[%SAMPLINGINTERVALADC][] = asyncBuffer[i][%SAMPLINGINTERVALADC][q] + MultiThread TPResults[%TPLENGTHPOINTSDAC][] = asyncBuffer[i][%TPLENGTHPOINTSDAC][q] + MultiThread TPResults[%PULSELENGTHPOINTSDAC][] = asyncBuffer[i][%PULSELENGTHPOINTSDAC][q] + MultiThread TPResults[%PULSESTARTPOINTSDAC][] = asyncBuffer[i][%PULSESTARTPOINTSDAC][q] + MultiThread TPResults[%SAMPLINGINTERVALDAC][] = asyncBuffer[i][%SAMPLINGINTERVALDAC][q] // Remove finished results from buffer DeletePoints i, 1, asyncBuffer @@ -270,7 +325,7 @@ Function TP_ROAnalysis(dfr, err, errmsg) TP_AutoAmplitudeAndBaseline(device, TPResults, marker) DQ_ApplyAutoBias(device, TPResults) - TP_RecordTP(device, TPResults, now, marker, timeStamp, timeStampUTC) + TP_RecordTP(device, TPResults, inData[%NOW]) endif End @@ -886,24 +941,33 @@ threadsafe Function/DF TP_TSAnalysis(dfrInp) DFREF dfrInp variable evalRange, refTime, refPoint, tpStartPoint - variable sampleInt, jsonId + variable jsonId variable avgBaselineSS, avgTPSS, instVal, evalOffsetPointsCorrected, instPoint + STRUCT TPZMQData tpzmq DFREF dfrOut = NewFreeDataFolder() - WAVE data = dfrInp:param0 - NVAR/SDFR=dfrInp clampAmp = param1 - NVAR/SDFR=dfrInp clampMode = param2 - NVAR/SDFR=dfrInp duration = param3 - NVAR/SDFR=dfrInp baselineFrac = param4 - NVAR/SDFR=dfrInp lengthTPInPoints = param5 - NVAR/SDFR=dfrInp now = param6 - NVAR/SDFR=dfrInp hsIndex = param7 - SVAR/SDFR=dfrInp device = param8 - NVAR/SDFR=dfrInp marker = param9 - NVAR/SDFR=dfrInp activeADCs = param10 - NVAR/SDFR=dfrInp timeStamp = param11 - NVAR/SDFR=dfrInp timeStampUTC = param12 + // see TP_PrepareAnalysisDF for order + WAVE data = dfrInp:param0 + NVAR/SDFR=dfrInp clampAmp = param1 + NVAR/SDFR=dfrInp clampMode = param2 + NVAR/SDFR=dfrInp pulseLengthPointsADC = param3 + NVAR/SDFR=dfrInp baselineFrac = param4 + NVAR/SDFR=dfrInp tpLengthPointsADC = param5 + NVAR/SDFR=dfrInp now = param6 + NVAR/SDFR=dfrInp headstage = param7 + SVAR/SDFR=dfrInp device = param8 + NVAR/SDFR=dfrInp marker = param9 + NVAR/SDFR=dfrInp activeADCs = param10 + NVAR/SDFR=dfrInp timeStamp = param11 + NVAR/SDFR=dfrInp timeStampUTC = param12 + NVAR/SDFR=dfrInp cycleId = param13 + NVAR/SDFR=dfrInp pulseStartPointsADC = param14 + NVAR/SDFR=dfrInp samplingIntervalADC = param15 + NVAR/SDFR=dfrInp tpLengthPointsDAC = param16 + NVAR/SDFR=dfrInp pulseLengthPointsDAC = param17 + NVAR/SDFR=dfrInp pulseStartPointsDAC = param18 + NVAR/SDFR=dfrInp samplingIntervalDAC = param19 #if defined(TP_ANALYSIS_DEBUGGING) DEBUGPRINT_TS("Marker: ", var = marker) @@ -914,43 +978,32 @@ threadsafe Function/DF TP_TSAnalysis(dfrInp) colors[0, lengthTPInPoints - 1] = 100 #endif - // Rows: - // 0: base line level - // 1: steady state resistance - // 2: instantaneous resistance - // 3: averaged elevated level (steady state) - // 4: averaged elevated level (instantaneous) - Make/N=5/D dfrOut:outData/WAVE=outData - SetDimLabel ROWS, 0, BASELINE, outData - SetDimLabel ROWS, 1, STEADYSTATERES, outData - SetDimLabel ROWS, 2, INSTANTRES, outData - SetDimLabel ROWS, 3, ELEVATED_SS, outData - SetDimLabel ROWS, 4, ELEVATED_INST, outData - - sampleInt = DimDelta(data, ROWS) - tpStartPoint = baseLineFrac * lengthTPInPoints - evalRange = min(5 / sampleInt, min(duration * 0.2, tpStartPoint * 0.2)) * sampleInt + Make/N=(ItemsInList(TP_ANALYSIS_DATA_LABELS))/D dfrOut:outData/WAVE=outData + SetDimensionLabels(outData, TP_ANALYSIS_DATA_LABELS, ROWS) + + tpStartPoint = baseLineFrac * tpLengthPointsADC + evalRange = min(5 / samplingIntervalADC, min(pulseLengthPointsADC * 0.2, tpStartPoint * 0.2)) * samplingIntervalADC // correct TP_EVAL_POINT_OFFSET for the non-standard sampling interval - evalOffsetPointsCorrected = (TP_EVAL_POINT_OFFSET / sampleInt) * HARDWARE_ITC_MIN_SAMPINT + evalOffsetPointsCorrected = (TP_EVAL_POINT_OFFSET / samplingIntervalADC) * HARDWARE_ITC_MIN_SAMPINT - refTime = (tpStartPoint - evalOffsetPointsCorrected) * sampleInt + refTime = (tpStartPoint - evalOffsetPointsCorrected) * samplingIntervalADC AvgBaselineSS = mean(data, refTime - evalRange, refTime) #if defined(TP_ANALYSIS_DEBUGGING) // color BASE - variable refpt = refTime / sampleInt - colors[refpt - evalRange / sampleInt, refpt] = 50 - DEBUGPRINT_TS("SampleInt: ", var = sampleInt) + variable refpt = refTime / samplingIntervalADC + colors[refpt - evalRange / samplingIntervalADC, refpt] = 50 + DEBUGPRINT_TS("SampleInt: ", var = samplingIntervalADC) DEBUGPRINT_TS("tpStartPoint: ", var = tpStartPoint) DEBUGPRINT_TS("evalRange (ms): ", var = evalRange) - DEBUGPRINT_TS("evalRange in points: ", var = evalRange / sampleInt) + DEBUGPRINT_TS("evalRange in points: ", var = evalRange / samplingIntervalADC) DEBUGPRINT_TS("Base range begin (ms): ", var = refTime - evalRange) DEBUGPRINT_TS("Base range eng (ms): ", var = refTime) DEBUGPRINT_TS("average BaseLine: ", var = AvgBaselineSS) #endif - refTime = (lengthTPInPoints - tpStartPoint - evalOffsetPointsCorrected) * sampleInt + refTime = (tpLengthPointsADC - tpStartPoint - evalOffsetPointsCorrected) * samplingIntervalADC avgTPSS = mean(data, refTime - evalRange, refTime) #if defined(TP_ANALYSIS_DEBUGGING) @@ -958,16 +1011,16 @@ threadsafe Function/DF TP_TSAnalysis(dfrInp) DEBUGPRINT_TS("steady state range eng (ms): ", var = refTime) DEBUGPRINT_TS("steady state average: ", var = avgTPSS) // color steady state - refpt = lengthTPInPoints - tpStartPoint - evalOffsetPointsCorrected - colors[refpt - evalRange / sampleInt, refpt] = 50 + refpt = lengthTPInPoints - tpStartPoint - evalOffsetPointsCorrected + colors[refpt - evalRange / samplingIntervalADC, refpt] = 50 // color instantaneous - refpt = tpStartPoint + evalOffsetPointsCorrected - colors[refpt, refpt + 0.25 / sampleInt] = 50 + refpt = tpStartPoint + evalOffsetPointsCorrected + colors[refpt, refpt + 0.25 / samplingIntervalADC] = 50 #endif refPoint = tpStartPoint + evalOffsetPointsCorrected // as data is always too small for threaded execution, the values of V_minRowLoc/V_maxRowLoc are reproducible - WaveStats/P/Q/M=1/R=[refPoint, refPoint + 0.25 / sampleInt] data + WaveStats/P/Q/M=1/R=[refPoint, refPoint + 0.25 / samplingIntervalADC] data instPoint = (clampAmp < 0) ? V_minRowLoc : V_maxRowLoc if(instPoint == -1) // all wave data is NaN @@ -983,92 +1036,73 @@ threadsafe Function/DF TP_TSAnalysis(dfrInp) #endif if(clampMode == I_CLAMP_MODE) - outData[1] = (avgTPSS - avgBaselineSS) * MILLI_TO_ONE / (clampAmp * PICO_TO_ONE) * ONE_TO_MEGA - outData[2] = (instVal - avgBaselineSS) * MILLI_TO_ONE / (clampAmp * PICO_TO_ONE) * ONE_TO_MEGA + outData[%STEADYSTATERES] = (avgTPSS - avgBaselineSS) * MILLI_TO_ONE / (clampAmp * PICO_TO_ONE) * ONE_TO_MEGA + outData[%INSTANTRES] = (instVal - avgBaselineSS) * MILLI_TO_ONE / (clampAmp * PICO_TO_ONE) * ONE_TO_MEGA else - outData[1] = (clampAmp * MILLI_TO_ONE) / ((avgTPSS - avgBaselineSS) * PICO_TO_ONE) * ONE_TO_MEGA - outData[2] = (clampAmp * MILLI_TO_ONE) / ((instVal - avgBaselineSS) * PICO_TO_ONE) * ONE_TO_MEGA + outData[%STEADYSTATERES] = (clampAmp * MILLI_TO_ONE) / ((avgTPSS - avgBaselineSS) * PICO_TO_ONE) * ONE_TO_MEGA + outData[%INSTANTRES] = (clampAmp * MILLI_TO_ONE) / ((instVal - avgBaselineSS) * PICO_TO_ONE) * ONE_TO_MEGA endif - outData[0] = avgBaselineSS - outData[3] = avgTPSS - outData[4] = instVal + outData[%BASELINE] = avgBaselineSS + outData[%ELEVATED_SS] = avgTPSS + outData[%ELEVATED_INST] = instVal #if defined(TP_ANALYSIS_DEBUGGING) - DEBUGPRINT_TS("instantaneous resistance: ", var = outData[2]) - DEBUGPRINT_TS("steady state resistance: ", var = outData[1]) + DEBUGPRINT_TS("instantaneous resistance: ", var = outData[%INSTANTRES]) + DEBUGPRINT_TS("steady state resistance: ", var = outData[%STEADYSTATERES]) #endif // additional data copy - variable/G dfrOut:now = now - variable/G dfrOut:hsIndex = hsIndex - string/G dfrOut:device = device - variable/G dfrOut:marker = marker - variable/G dfrOut:activeADCs = activeADCs - variable/G dfrOut:timeStamp = timeStamp - variable/G dfrOut:timeStampUTC = timeStampUTC - - // ZMQ publishing - jsonId = JSON_New() - JSON_AddTreeObject(jsonID, "properties") - JSON_AddVariable(jsonID, "properties/unique tp marker", marker) - JSON_AddString(jsonID, "properties/device", device) - JSON_AddVariable(jsonID, "properties/headstage", hsIndex) - JSON_AddVariable(jsonID, "properties/time of tp acquisition", now) - JSON_AddVariable(jsonID, "properties/clamp mode", clampMode) - JSON_AddVariable(jsonID, "properties/clamp amplitude", clampAmp) - JSON_AddVariable(jsonID, "properties/pulse duration in points", duration) - JSON_AddVariable(jsonID, "properties/baseline fraction", baselineFrac) - JSON_AddVariable(jsonID, "properties/length of tp in sample points", lengthTPInPoints) - JSON_AddVariable(jsonID, "properties/sample interval", sampleInt) - JSON_AddVariable(jsonID, "properties/timeStamp", timeStamp) - JSON_AddVariable(jsonID, "properties/timeStampUTC", timeStampUTC) - JSON_AddTreeObject(jsonID, "results") - JSON_AddVariable(jsonID, "results/average baseline steady state", avgBaselineSS) - JSON_AddVariable(jsonID, "results/average tp steady state", avgTPSS) - JSON_AddVariable(jsonID, "results/instantaneous", instVal) - JSON_AddVariable(jsonID, "results/steady state resistance", outData[1]) - JSON_AddVariable(jsonID, "results/instantaneous resistance", outData[2]) - - PUB_Publish(jsonID, ZMQ_FILTER_TPRESULT_NOW, releaseJSON = 0) - if(TP_CheckPublishingTime(ZMQ_FILTER_TPRESULT_1S, 1)) - PUB_Publish(jsonID, ZMQ_FILTER_TPRESULT_1S, releaseJSON = 0) - endif - if(TP_CheckPublishingTime(ZMQ_FILTER_TPRESULT_5S, 5)) - PUB_Publish(jsonID, ZMQ_FILTER_TPRESULT_5S, releaseJSON = 0) - endif - if(TP_CheckPublishingTime(ZMQ_FILTER_TPRESULT_10S, 10)) - PUB_Publish(jsonID, ZMQ_FILTER_TPRESULT_10S, releaseJSON = 0) - endif - JSON_Release(jsonID) + string/G dfrOut:device = device + outData[%NOW] = now + outData[%HEADSTAGE] = headstage + outData[%MARKER] = marker + outData[%NUMBER_OF_TP_CHANNELS] = activeADCs + outData[%TIMESTAMP] = timestamp + outData[%TIMESTAMPUTC] = timestampUTC + outData[%CLAMPMODE] = clampMode + outData[%CLAMPAMP] = clampAmp + outData[%BASELINEFRAC] = baselineFrac + outData[%CYCLEID] = cycleId + outData[%TPLENGTHPOINTSADC] = tpLengthPointsADC + outData[%PULSELENGTHPOINTSADC] = pulseLengthPointsADC + outData[%PULSESTARTPOINTSADC] = pulseStartPointsADC + outData[%SAMPLINGINTERVALADC] = samplingIntervalADC + outData[%TPLENGTHPOINTSDAC] = tpLengthPointsDAC + outData[%PULSELENGTHPOINTSDAC] = pulseLengthPointsDAC + outData[%PULSESTARTPOINTSDAC] = pulseStartPointsDAC + outData[%SAMPLINGINTERVALDAC] = samplingIntervalDAC + + // Serialize for ZMQ publishing + tpzmq.marker = marker + tpzmq.device = device + tpzmq.headstage = headstage + tpzmq.now = now + tpzmq.clampMode = clampMode + tpzmq.clampAmp = clampAmp + tpzmq.tpLengthPointsADC = tpLengthPointsADC + tpzmq.pulseLengthPointsADC = pulseLengthPointsADC + tpzmq.pulseStartPointsADC = pulseStartPointsADC + tpzmq.samplingIntervalADC = samplingIntervalADC + tpzmq.tpLengthPointsDAC = tpLengthPointsDAC + tpzmq.pulseLengthPointsDAC = pulseLengthPointsDAC + tpzmq.pulseStartPointsDAC = pulseStartPointsDAC + tpzmq.samplingIntervalDAC = samplingIntervalDAC + tpzmq.baselineFrac = baselineFrac + tpzmq.timeStamp = timeStamp + tpzmq.timeStampUTC = timeStampUTC + tpzmq.cycleId = cycleId + + tpzmq.avgBaselineSS = avgBaselineSS + tpzmq.avgTPSS = avgTPSS + tpzmq.instVal = instVal + tpzmq.resistanceSS = outData[%STEADYSTATERES] + tpzmq.resistanceInst = outData[%INSTANTRES] + + PUB_TPResult(tpzmq) return dfrOut End -/// @brief Updates the publishing timestamp in the TUFXOP storage and returns 1 if an update is due (0 otherwise) -threadsafe static Function TP_CheckPublishingTime(string pubFilter, variable period) - - variable curTime - - TUFXOP_AcquireLock/N=(pubFilter) - TUFXOP_GetStorage/Z/Q/N=(pubFilter) lastUpdated - if(V_flag) - TUFXOP_Init/N=(pubFilter) - TUFXOP_GetStorage/Z/N=(pubFilter) lastUpdated - Make/FREE/D dTime = {DateTime} - lastUpdated[0] = dTime - endif - curTime = DateTime - WAVE lastTime = lastUpdated[0] - if(lastTime[0] + period > curTime) - lastTime[0] = curTime + period - TUFXOP_ReleaseLock/N=(pubFilter) - return 1 - endif - TUFXOP_ReleaseLock/N=(pubFilter) - - return 0 -End - /// @brief Calculates running average [box average] for all entries and all headstages static Function TP_CalculateAverage(WAVE TPResultsBuffer, WAVE TPResults) variable numEntries, numLayers @@ -1096,9 +1130,9 @@ End /// @brief Records values from TPResults into TPStorage at defined intervals. /// /// Used for analysis of TP over time. -static Function TP_RecordTP(string device, WAVE TPResults, variable now, variable tpMarker, variable timeStamp, variable timeStampUTC) +static Function TP_RecordTP(string device, WAVE TPResults, variable now) - variable delta, i, ret, lastPressureCtrl, cycleID + variable delta, i, ret, lastPressureCtrl WAVE TPStorage = GetTPStorage(device) WAVE hsProp = GetHSProperties(device) variable count = GetNumberFromWaveNote(TPStorage, NOTE_INDEX) @@ -1138,9 +1172,9 @@ static Function TP_RecordTP(string device, WAVE TPResults, variable now, variabl : TPStorage[count][q][%HoldingCmd_IC] endif - TPStorage[count][][%TimeInSeconds] = now - TPStorage[count][][%TimeStamp] = timestamp - TPStorage[count][][%TimeStampSinceIgorEpochUTC] = timeStampUTC + TPStorage[count][][%TimeInSeconds] = TPResults[%NOW][q] + TPStorage[count][][%TimeStamp] = TPResults[%TIMESTAMP][q] + TPStorage[count][][%TimeStampSinceIgorEpochUTC] = TPResults[%TIMESTAMPUTC][q] TPStorage[count][][%PeakResistance] = min(TPResults[%ResistanceInst][q], TP_MAX_VALID_RESISTANCE) TPStorage[count][][%SteadyStateResistance] = min(TPResults[%ResistanceSteadyState][q], TP_MAX_VALID_RESISTANCE) @@ -1151,21 +1185,29 @@ static Function TP_RecordTP(string device, WAVE TPResults, variable now, variabl TPStorage[count][][%ADC] = hsProp[q][%ADC] TPStorage[count][][%Headstage] = hsProp[q][%Enabled] ? q : NaN TPStorage[count][][%ClampMode] = hsProp[q][%ClampMode] + TPStorage[count][][%CLAMPAMP] = TPResults[%CLAMPAMP][q] TPStorage[count][][%Baseline_VC] = hsProp[q][%ClampMode] == V_CLAMP_MODE ? TPResults[%BaselineSteadyState][q] : NaN TPStorage[count][][%Baseline_IC] = hsProp[q][%ClampMode] == I_CLAMP_MODE ? TPResults[%BaselineSteadyState][q] : NaN TPStorage[count][][%DeltaTimeInSeconds] = count > 0 ? now - TPStorage[0][0][%TimeInSeconds] : 0 - TPStorage[count][][%TPMarker] = tpMarker + TPStorage[count][][%TPMarker] = TPResults[%MARKER][q] - cycleID = ROVAR(GetTestpulseCycleID(device)) - TPStorage[count][][%TPCycleID] = cycleID + TPStorage[count][][%TPCycleID] = TPResults[%CYCLEID][q] TPStorage[count][][%AutoTPAmplitude] = TPResults[%AutoTPAmplitude][q] TPStorage[count][][%AutoTPBaseline] = TPResults[%AutoTPBaseline][q] TPStorage[count][][%AutoTPBaselineRangeExceeded] = TPResults[%AutoTPBaselineRangeExceeded][q] TPStorage[count][][%AutoTPBaselineFitResult] = TPResults[%AutoTPBaselineFitResult][q] TPStorage[count][][%AutoTPDeltaV] = TPResults[%AutoTPDeltaV][q] + TPStorage[count][][%TPLENGTHPOINTSADC] = TPResults[%TPLENGTHPOINTSADC][q] + TPStorage[count][][%PULSELENGTHPOINTSADC] = TPResults[%PULSELENGTHPOINTSADC][q] + TPStorage[count][][%PULSESTARTPOINTSADC] = TPResults[%PULSESTARTPOINTSADC][q] + TPStorage[count][][%SAMPLINGINTERVALADC] = TPResults[%SAMPLINGINTERVALADC][q] + TPStorage[count][][%TPLENGTHPOINTSDAC] = TPResults[%TPLENGTHPOINTSDAC][q] + TPStorage[count][][%PULSELENGTHPOINTSDAC] = TPResults[%PULSELENGTHPOINTSDAC][q] + TPStorage[count][][%PULSESTARTPOINTSDAC] = TPResults[%PULSESTARTPOINTSDAC][q] + TPStorage[count][][%SAMPLINGINTERVALDAC] = TPResults[%SAMPLINGINTERVALDAC][q] WAVE TPSettings = GetTPSettings(device) TPStorage[count][][%AutoTPCycleID] = hsProp[q][%Enabled] ? TPSettings[%autoTPCycleID][q] : NaN @@ -1587,9 +1629,9 @@ Function/DF TP_PrepareAnalysisDF(string device, STRUCT TPAnalysisInput &tpInput) ASYNC_AddParam(threadDF, w = tpInput.data) ASYNC_AddParam(threadDF, var = tpInput.clampAmp) ASYNC_AddParam(threadDF, var = tpInput.clampMode) - ASYNC_AddParam(threadDF, var = tpInput.duration) + ASYNC_AddParam(threadDF, var = tpInput.pulseLengthPointsADC) ASYNC_AddParam(threadDF, var = tpInput.baselineFrac) - ASYNC_AddParam(threadDF, var = tpInput.tpLengthPoints) + ASYNC_AddParam(threadDF, var = tpInput.tpLengthPointsADC) ASYNC_AddParam(threadDF, var = tpInput.readTimeStamp) ASYNC_AddParam(threadDF, var = tpInput.hsIndex) ASYNC_AddParam(threadDF, str = tpInput.device) @@ -1597,6 +1639,13 @@ Function/DF TP_PrepareAnalysisDF(string device, STRUCT TPAnalysisInput &tpInput) ASYNC_AddParam(threadDF, var = tpInput.activeADCs) ASYNC_AddParam(threadDF, var = tpInput.timeStamp) ASYNC_AddParam(threadDF, var = tpInput.timeStampUTC) + ASYNC_AddParam(threadDF, var = tpInput.cycleId) + ASYNC_AddParam(threadDF, var = tpInput.pulseStartPointsADC) + ASYNC_AddParam(threadDF, var = tpInput.samplingIntervalADC) + ASYNC_AddParam(threadDF, var = tpInput.tpLengthPointsDAC) + ASYNC_AddParam(threadDF, var = tpInput.pulseLengthPointsDAC) + ASYNC_AddParam(threadDF, var = tpInput.pulseStartPointsDAC) + ASYNC_AddParam(threadDF, var = tpInput.samplingIntervalDAC) return threadDF End diff --git a/Packages/MIES/MIES_WaveDataFolderGetters.ipf b/Packages/MIES/MIES_WaveDataFolderGetters.ipf index a2627a860e..cf604d0bca 100644 --- a/Packages/MIES/MIES_WaveDataFolderGetters.ipf +++ b/Packages/MIES/MIES_WaveDataFolderGetters.ipf @@ -495,22 +495,15 @@ End /// - Layers: /// - 0: marker /// - 1: received channels -/// - 2: now -/// Column 1: baseline level -/// Column 2: steady state res -/// Column 3: instantaneous res -/// Column 4: baseline position -/// Column 5: steady state res position -/// Column 6: instantaneous res position -/// Column 7: average elevated level (steady state) -/// Column 8: average elevated level (instantaneous) +/// Column 1+: defined through TP_ANALYSIS_DATA_LABELS /// /// Layers: -/// - NUM_HEADSTAGES positions with value entries at hsIndex +/// - NUM_HEADSTAGES positions with value entries at headstage Function/WAVE GetTPResultAsyncBuffer(device) string device - variable versionOfNewWave = 1 + variable versionOfNewWave = 2 + variable numCols = ItemsInList(TP_ANALYSIS_DATA_LABELS) + 1 DFREF dfr = GetDeviceTestPulse(device) @@ -519,24 +512,16 @@ Function/WAVE GetTPResultAsyncBuffer(device) if(ExistsWithCorrectLayoutVersion(wv, versionOfNewWave)) return wv elseif(WaveExists(wv)) - Redimension/N=(-1, 9, -1) wv + Redimension/N=(-1, numCols, -1) wv else - Make/N=(0, 9, NUM_HEADSTAGES)/D dfr:TPResultAsyncBuffer/WAVE=wv + Make/N=(0, numCols, NUM_HEADSTAGES)/D dfr:TPResultAsyncBuffer/WAVE=wv endif SetDimLabel COLS, 0, ASYNCDATA, wv - SetDimLabel COLS, 1, BASELINE, wv - SetDimLabel COLS, 2, STEADYSTATERES, wv - SetDimLabel COLS, 3, INSTANTRES, wv - SetDimLabel COLS, 4, BASELINE_POS, wv - SetDimLabel COLS, 5, STEADYSTATERES_POS, wv - SetDimLabel COLS, 6, INSTANTRES_POS, wv - SetDimLabel COLS, 7, ELEVATED_SS, wv - SetDimLabel COLS, 8, ELEVATED_INST, wv + SetDimensionLabels(wv, TP_ANALYSIS_DATA_LABELS, COLS, startPos = 1) SetDimLabel LAYERS, 0, MARKER, wv SetDimLabel LAYERS, 1, REC_CHANNELS, wv - SetDimLabel LAYERS, 2, NOW, wv SetWaveVersion(wv, versionOfNewWave) @@ -3022,34 +3007,21 @@ Function/WAVE GetTPStorage(device) string device DFREF dfr = GetDeviceTestPulse(device) - variable versionOfNewWave = 15 + variable versionOfNewWave = 16 WAVE/Z/SDFR=dfr/D wv = TPStorage if(ExistsWithCorrectLayoutVersion(wv, versionOfNewWave)) return wv elseif(WaveExists(wv)) - Redimension/N=(-1, NUM_HEADSTAGES, 31)/D wv + Redimension/N=(-1, NUM_HEADSTAGES, 39)/D wv - if(WaveVersionIsSmaller(wv, 10)) + if(WaveVersionIsSmaller(wv, 16)) wv[][][17] = NaN - wv[][][20, 21] = NaN - endif - if(WaveVersionIsSmaller(wv, 11)) - wv[][][22] = NaN - endif - // no size change on version 12 - if(WaveVersionIsSmaller(wv, 13)) - wv[][][23] = NaN - endif - if(WaveVersionIsSmaller(wv, 14)) - wv[][][24] = NaN - endif - if(WaveVersionIsSmaller(wv, 15)) - wv[][][25, 30] = NaN + wv[][][20, 39] = NaN endif else - Make/N=(MINIMUM_WAVE_SIZE_LARGE, NUM_HEADSTAGES, 31)/D dfr:TPStorage/WAVE=wv + Make/N=(MINIMUM_WAVE_SIZE_LARGE, NUM_HEADSTAGES, 40)/D dfr:TPStorage/WAVE=wv wv = NaN @@ -3089,6 +3061,15 @@ Function/WAVE GetTPStorage(device) SetDimLabel LAYERS, 28, AutoTPCycleID, wv SetDimLabel LAYERS, 29, AutoTPBaselineFitResult, wv SetDimLabel LAYERS, 30, AutoTPDeltaV, wv + SetDimLabel LAYERS, 31, CLAMPAMP, wv + SetDimLabel LAYERS, 32, TPLENGTHPOINTSADC, wv + SetDimLabel LAYERS, 33, PULSELENGTHPOINTSADC, wv + SetDimLabel LAYERS, 34, PULSESTARTPOINTSADC, wv + SetDimLabel LAYERS, 35, SAMPLINGINTERVALADC, wv + SetDimLabel LAYERS, 36, TPLENGTHPOINTSDAC, wv + SetDimLabel LAYERS, 37, PULSELENGTHPOINTSDAC, wv + SetDimLabel LAYERS, 38, PULSESTARTPOINTSDAC, wv + SetDimLabel LAYERS, 39, SAMPLINGINTERVALDAC, wv SetNumberInWaveNote(wv, AUTOBIAS_LAST_INVOCATION_KEY, 0) SetNumberInWaveNote(wv, DIMENSION_SCALING_LAST_INVOC, 0) @@ -3272,11 +3253,17 @@ End /// - 7: Auto TP Baseline range exceeded: True/False /// - 8: Auto TP Baseline fit result: One of @ref TPBaselineFitResults /// - 9: Auto TP Delta V: [mV] -/// +/// - 10+: partial dim labels from TP_ANALYSIS_DATA_LABELS, originally filled in TP_TSAnalysis /// Columns: /// - NUM_HEADSTAGES Function/WAVE GetTPResults(string device) - variable version = 3 + variable version = 4 + + string labels = "ResistanceInst;BaselineSteadyState;ResistanceSteadyState;ElevatedSteadyState;ElevatedInst;" + \ + "AutoTPAmplitude;AutoTPBaseline;AutoTPBaselineRangeExceeded;AutoTPBaselineFitResult;AutoTPDeltaV;" + \ + "NOW;HEADSTAGE;MARKER;NUMBER_OF_TP_CHANNELS;TIMESTAMP;TIMESTAMPUTC;CLAMPMODE;CLAMPAMP;BASELINEFRAC;" + \ + "CYCLEID;TPLENGTHPOINTSADC;PULSELENGTHPOINTSADC;PULSESTARTPOINTSADC;SAMPLINGINTERVALADC;TPLENGTHPOINTSDAC;" + \ + "PULSELENGTHPOINTSDAC;PULSESTARTPOINTSDAC;SAMPLINGINTERVALDAC;" DFREF dfr = GetDeviceTestPulse(device) WAVE/D/Z/SDFR=dfr wv = results @@ -3284,10 +3271,10 @@ Function/WAVE GetTPResults(string device) if(ExistsWithCorrectLayoutVersion(wv, version)) return wv elseif(WaveExists(wv)) - Redimension/D/N=(10, NUM_HEADSTAGES) wv + Redimension/D/N=(ItemsInList(labels), NUM_HEADSTAGES) wv wv = NaN else - Make/D/N=(10, NUM_HEADSTAGES) dfr:results/WAVE=wv + Make/D/N=(ItemsInList(labels), NUM_HEADSTAGES) dfr:results/WAVE=wv wv = NaN // initialize with the old 1D waves @@ -3303,7 +3290,7 @@ Function/WAVE GetTPResults(string device) KillOrMoveToTrash(wv = SSResistance) endif - SetDimensionLabels(wv, "ResistanceInst;BaselineSteadyState;ResistanceSteadyState;ElevatedSteadyState;ElevatedInst;AutoTPAmplitude;AutoTPBaseline;AutoTPBaselineRangeExceeded;AutoTPBaselineFitResult;AutoTPDeltaV", ROWS) + SetDimensionLabels(wv, labels, ROWS) SetWaveVersion(wv, version)