Skip to content

Commit

Permalink
TP: Added two functions that allow to retrieve info about TPs
Browse files Browse the repository at this point in the history
Added TP_GetStoredTP and TP_GetStoredTPsFromCycle that allow to get
information about a TP by tpMarker or TPs by cycle id.

- both function allow to recreate the DA wave for the TPs with the flag includeDAC
- the returned data includes the AD, DA data as well as meta informations for
  each returned TP (from TPStorage).

- the former function TP_GetStoredTPs was renamed to TP_GetConsecutiveTPsUptoMarker
  to prevent misleading naming.
- These TP functions use the same TP utility function.
  • Loading branch information
MichaelHuth committed Aug 22, 2024
1 parent 6368bbb commit 9c33299
Show file tree
Hide file tree
Showing 3 changed files with 235 additions and 25 deletions.
169 changes: 151 additions & 18 deletions Packages/MIES/MIES_TestPulse.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -106,45 +106,178 @@ 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_GetStoredTPs(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

/// @brief Returns data about a stored TestPulse from a given tpMarker
///
/// Returns a wave reference wave with 3 entries:
/// 0 : numeric wave with the acquired AD data of the test pulse (signal) in the format as created by @ref TP_StoreTP
/// 1 : numeric wave with the recreated DA data of the test pulse (command)
/// 2 : Additional information for the test pulse from creation and analysis in the format described for @ref GetTPStorage
/// As the information is for a single TP only, the wave contains a single slice (1 row)
///
/// @param device device name
/// @param tpMarker testpulse marker
/// @param includeDAC flag, when set the DAC wave of the testpulse is recreated
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][%TPLENGTHPOINTSDAC][0], tpResult[0][headstage][%PULSESTARTPOINTSDAC], tpResult[0][headstage][%PULSELENGTHPOINTSDAC])
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 Returns data about stored TestPulses from a given cycle id
///
/// Returns a wave reference wave with 3 entries:
/// 0 : wave ref wave that stores numeric waves with the acquired AD data of the test pulse (signal) in the format as created by @ref TP_StoreTP
/// The number of elements in the wave ref wave equals the number of test pulses in the cycle.
/// 1 : numeric wave with the recreated DA data of the test pulse (command)
/// Note: here only a single wave is recreated because the DA data for all test pulses of that cycle is identical
/// 2 : wave ref wave that stores additional information for the test pulses from creation and analysis in the format described for @ref GetTPStorage
/// The number of elements in the wave ref wave equals the number of test pulses in the cycle and has the same order as the signal waves from index 0.
/// Each element is a single slice (1 row) of tpStorage.
///
/// If no test pulses exist for the given cycle id a null wave is returned.
///
/// @param device device name
/// @param cycleId test pulse cycle id
/// @param includeDAC flag, when set the DAC wave of the testpulse is recreated
Function/WAVE TP_GetStoredTPsFromCycle(string device, variable cycleId, variable includeDAC)

variable i, numEntries, dimMarker, headstage, numStored, numIndices, marker

includeDAC = !!includeDAC

WAVE/WAVE tpStored = GetStoredTestPulseWave(device)
numStored = GetNumberFromWaveNote(tpStored, NOTE_INDEX)
Make/FREE/D/N=(numStored) matchCycleId
matchCycleId[] = cycleId == GetNumberFromWaveNote(tpStored[p], "TPCycleID") ? p : NaN
WAVE/Z tpIndices = ZapNaNs(matchCycleId)
if(!WaveExists(tpIndices))
return $""
endif

numIndices = DimSize(tpIndices, ROWS)
Make/FREE/WAVE/N=(numIndices) tpsADC
tpsADC[] = tpStored[tpIndices[p]]

Make/FREE/D/N=(numIndices) tpMarkers
tpMarkers[] = GetNumberFromWaveNote(tpsADC[p], "TPMarker")

WAVE tpStorage = GetTPStorage(device)
numEntries = GetNumberFromWaveNote(tpStorage, NOTE_INDEX)
dimMarker = FindDimLabel(tpStorage, LAYERS, "TPMarker")

Make/FREE/WAVE/N=(numIndices) tpsResult
for(marker : tpMarkers)

FindValue/RMD=[][0][dimMarker]/V=(marker) tpStorage
ASSERT(V_row >= 0, "Inconsistent TP data")
Duplicate/FREE/RMD=[V_row][][] tpStorage, tpResult
tpsResult[i] = tpResult
i += 1
endfor

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][%TPLENGTHPOINTSDAC][0], tpResult[0][headstage][%PULSESTARTPOINTSDAC], tpResult[0][headstage][%PULSELENGTHPOINTSDAC])
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

if(number > V_row + 1)
Make/FREE/WAVE tpAll = {tpsADC, tpDAC, tpsResult}

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)

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

Expand Down Expand Up @@ -318,7 +451,7 @@ End
/// - Active headstages
static Function/WAVE TP_GetTPWaveForAutoTP(string device, variable marker)

WAVE/WAVE/Z TPs = TP_GetStoredTPs(device, marker, 2)
WAVE/WAVE/Z TPs = TP_GetConsecutiveTPsUptoMarker(device, marker, 2)

if(!WaveExists(TPs))
return $""
Expand Down
14 changes: 7 additions & 7 deletions Packages/tests/Basic/UTF_Testpulse.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -39,29 +39,29 @@ static Function FetchingTestpulsesWorks()
string device = "myDevice"

// emty stored TPs
WAVE/Z result = TP_GetStoredTPs(device, 0xA, 1)
WAVE/Z result = TP_GetConsecutiveTPsUptoMarker(device, 0xA, 1)
CHECK_WAVE(result, NULL_WAVE)

TP_StoreTP(device, {1}, 0xA, "I_DONT_CARE")

// not found
WAVE/Z result = TP_GetStoredTPs(device, 0xB, 1)
WAVE/Z result = TP_GetConsecutiveTPsUptoMarker(device, 0xB, 1)
CHECK_WAVE(result, NULL_WAVE)

// requested too many
WAVE/Z result = TP_GetStoredTPs(device, 0xA, 2)
WAVE/Z result = TP_GetConsecutiveTPsUptoMarker(device, 0xA, 2)
CHECK_WAVE(result, NULL_WAVE)

TP_StoreTP(device, {2}, 0xB, "I_DONT_CARE")

// works with fetching one TP
WAVE/WAVE/Z result = TP_GetStoredTPs(device, 0xA, 1)
WAVE/WAVE/Z result = TP_GetConsecutiveTPsUptoMarker(device, 0xA, 1)
CHECK_WAVE(result, WAVE_WAVE)
CHECK_EQUAL_VAR(DimSize(result, ROWS), 1)
CHECK_EQUAL_WAVES(WaveRef(result, row = 0), {{1}}, mode = WAVE_DATA)

// works with fetching two TPs
WAVE/WAVE/Z result = TP_GetStoredTPs(device, 0xB, 2)
WAVE/WAVE/Z result = TP_GetConsecutiveTPsUptoMarker(device, 0xB, 2)
CHECK_WAVE(result, WAVE_WAVE)
CHECK_EQUAL_VAR(DimSize(result, ROWS), 2)
CHECK_EQUAL_WAVES(WaveRef(result, row = 0), {{1}}, mode = WAVE_DATA)
Expand All @@ -74,12 +74,12 @@ static Function FetchingTestpulsesWorks()
SetNumberInWaveNote(storedTPs[2], "TPCycleID", 4711)

// fetching one works
WAVE/WAVE/Z result = TP_GetStoredTPs(device, 0xC, 1)
WAVE/WAVE/Z result = TP_GetConsecutiveTPsUptoMarker(device, 0xC, 1)
CHECK_WAVE(result, WAVE_WAVE)
CHECK_EQUAL_VAR(DimSize(result, ROWS), 1)
CHECK_EQUAL_WAVES(WaveRef(result, row = 0), {{3}}, mode = WAVE_DATA)

// but two not because 0xB has a different cycle id
WAVE/WAVE/Z result = TP_GetStoredTPs(device, 0xC, 2)
WAVE/WAVE/Z result = TP_GetConsecutiveTPsUptoMarker(device, 0xC, 2)
CHECK_WAVE(result, NULL_WAVE)
End
77 changes: 77 additions & 0 deletions Packages/tests/HardwareBasic/UTF_TestPulseAndTPDuringDAQ.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,83 @@ static Function TPDuringDAQwithPS_PreAcq(device)
PGC_SetAndActivateControl(device, "check_settings_show_power", val = 1)
End

/// UTF_TD_GENERATOR DeviceNameGeneratorMD1
static Function GetStoredTPTest([str])
string str

STRUCT DAQSettings s
InitDAQSettingsFromString(s, "MD1_RA0_I0_L0_BKG1_STP1_TP1" + \
"__HS0_DA0_AD0_CM:IC:_ST:TestPulse:")

AcquireData_NG(s, str)

CtrlNamedBackGround StopTPAfterFiveSeconds, start=(ticks + TP_DURATION_S * 60), period=1, proc=StopTPAfterFiveSeconds_IGNORE
End

static Function GetStoredTPTest_REENTRY([str])
string str
variable sweepNo, marker, cycleId

CHECK_EQUAL_VAR(GetSetVariable(str, "SetVar_Sweep"), 0)

sweepNo = AFH_GetLastSweepAcquired(str)
CHECK_EQUAL_VAR(sweepNo, NaN)

WaitAndCheckStoredTPs_IGNORE(str, 1)

WAVE/Z TPStorage = GetTPStorage(str)
CHECK_WAVE(TPStorage, NUMERIC_WAVE)
marker = TPStorage[0][0][%TPMarker]
CHECK_NEQ_VAR(marker, NaN)

// Check GetStoredTP
WAVE/Z storedTPData = TP_GetStoredTP(str, NaN, 1)
CHECK_WAVE(storedTPData, NULL_WAVE)

WAVE/Z storedTPData = TP_GetStoredTP(str, marker, 1)
CHECK_WAVE(storedTPData, WAVE_WAVE)
CHECK_EQUAL_VAR(DimSize(storedTPData, ROWS), 3)

WAVE/WAVE tpData = storedTPData
WAVE/Z tpADC = tpData[0]
WAVE/Z tpDAC = tpData[1]
WAVE/Z tpInfo = tpData[2]

CHECK_WAVE(tpADC, NUMERIC_WAVE)
CHECK_GE_VAR(DimSize(tpADC, ROWS), 1)
CHECK_WAVE(tpDAC, NUMERIC_WAVE)
CHECK_GE_VAR(DimSize(tpDAC, ROWS), 1)

Duplicate/FREE/RMD=[0][][] TPStorage, tpResult
CHECK_EQUAL_WAVES(tpInfo, tpResult)

// Check TP_GetStoredTPsFromCycle
cycleId = TPStorage[0][0][%TPCycleID]
CHECK_NEQ_VAR(cycleId, NaN)

WAVE/Z storedTPData = TP_GetStoredTPsFromCycle(str, NaN, 1)
CHECK_WAVE(storedTPData, NULL_WAVE)

WAVE/Z storedTPData = TP_GetStoredTPsFromCycle(str, cycleId, 1)
CHECK_WAVE(storedTPData, WAVE_WAVE)
CHECK_EQUAL_VAR(DimSize(storedTPData, ROWS), 3)

WAVE/WAVE tpData = storedTPData
WAVE/WAVE/Z tpADC = tpData[0]
WAVE/Z tpDAC = tpData[1]
WAVE/WAVE/Z tpInfoWref = tpData[2]

CHECK_WAVE(tpADC, WAVE_WAVE)
CHECK_GE_VAR(DimSize(tpADC, ROWS), 1)
CHECK_WAVE(tpDAC, NUMERIC_WAVE)
CHECK_GE_VAR(DimSize(tpDAC, ROWS), 1)
CHECK_WAVE(tpInfoWref, WAVE_WAVE)
CHECK_EQUAL_VAR(DimSize(tpADC, ROWS), DimSize(tpInfoWref, ROWS))

WAVE tpInfo0 = tpInfoWref[0]
CHECK_EQUAL_WAVES(tpInfo0, tpResult)
End

// UTF_TD_GENERATOR DeviceNameGeneratorMD1
static Function TPDuringDAQwithPS([str])
string str
Expand Down

0 comments on commit 9c33299

Please sign in to comment.