Skip to content

Early sweep initiation when autobias target V is reached during repurposed time (please review, @t-b) #2700

@timjarsky

Description

@timjarsky

Context

When the autobias target V QC fails (e.g., in PSQ_DA_SCALE and related PatchSeq analysis functions), the remaining sweep time is repurposed to provide a window for the TP to bring the cell to the target voltage. Currently, the next sweep always starts after the repurposed time expires. However, it would be more efficient to start the next sweep as soon as the target voltage is reached during the TP, without waiting for the full repurposed interval.

Proposed Solution

@t-b, could you please evaluate this design and the implementation details below?

Summary

  1. Add a flag to indicate RA repurposed time is due to autobias target V QC failure.
  2. Arm a background task to monitor TPStorage Vrest during the ITI TP window.
  3. As soon as all active IC headstages report Vrest within the target range, immediately abort the ITI timer, stop the TP, and start the next sweep.
  4. If the timer expires first, proceed as before (standard fallback path).

Relevant Code Locations

  • PSQ_EvaluateBaselineProperties (MIES_AnalysisFunctions_PatchSeq.ipf): sets repurposed time and returns ANALYSIS_FUNC_RET_REPURP_TIME.
  • RA_HandleITI_MD (MIES_RepeatedAcquisition.ipf): starts the TP/test pulse and arms the ITI timer.
  • GetTPStorage (MIES_WaveDataFolderGetters.ipf): provides TPStorage for reading Vrest/mode.

Full Example Implementation

1. New flag in MIES_WaveDataFolderGetters.ipf

/// @brief Returns a flag indicating ITI repurposed time due to autobias target V QC failure (for early sweep trigger)
Function/S GetWaitingForAutobiasTargetV(string device)
	DFREF dfr = GetDevicePath(device)
	NVAR/Z/SDFR=dfr waitingForAutobiasTargetV
	if(!NVAR_Exists(waitingForAutobiasTargetV))
		variable/G dfr:waitingForAutobiasTargetV = 0
	endif
	return GetDataFolder(1, dfr) + "waitingForAutobiasTargetV"
End

2. Set the flag in PSQ_EvaluateBaselineProperties (MIES_AnalysisFunctions_PatchSeq.ipf)

Just before returning ANALYSIS_FUNC_RET_REPURP_TIME for a targetV QC fail:

igorpro
elseif(!targetVPassedAll)
	NVAR repurposedTime = $GetRepurposedSweepTime(device)
	NVAR waitingForTargetV = $GetWaitingForAutobiasTargetV(device) // NEW
	if(type == PSQ_CHIRP)
		repurposedTime = 6 - LeftOverSweepTime(device, fifoInStimsetTime + totalOnsetDelay)
	elseif(type == PSQ_DA_SCALE)
		repurposedTime = 5
	else
		repurposedTime = 10
	endif
#ifdef AUTOMATED_TESTING
	repurposedTime = 0.5
#endif
	waitingForTargetV = 1 // arm the early-exit monitor
	return ANALYSIS_FUNC_RET_REPURP_TIME

3. Monitor/abort repurposed wait if targetV is reached (RA_HandleITI_MD, MIES_RepeatedAcquisition.ipf)

After arming the ITI and TP:

igorpro
TPM_StartTPMultiDeviceLow(device, runModifier = TEST_PULSE_DURING_RA_MOD)
funcList = "TPM_StopTestPulseMultiDevice(\"" + device + "\")" + ";" + "RA_CounterMD(\"" + device + "\")"
DQM_StartBackgroundTimer(device, ITI, funcList)
// NEW monitor:
NVAR waitingForTargetV = $GetWaitingForAutobiasTargetV(device)
if(waitingForTargetV)
	waitingForTargetV = 0
	PSQ_StartAutobiasTargetVMonitor(device)
endif

4. Add the background monitor (in MIES_AnalysisFunctions_PatchSeq.ipf or similar)

igorpro

Function PSQ_StartAutobiasTargetVMonitor(string device)
	DFREF dfr = GetDevicePath(device)
	String/G dfr:autoBiasMonitorDevice = device
	CtrlNamedBackground PSQ_AutobiasMonitor, period=60, proc=PSQ_AutobiasMonitorTask, start
End

Function PSQ_AutobiasMonitorTask(STRUCT WMBackgroundStruct &s)
	DFREF dfr = root:MIES:HardwareDevices:
	SVAR/Z/SDFR=dfr monitorDeviceStr = autoBiasMonitorDevice
	if(!SVAR_Exists(monitorDeviceStr))
		return 1 // stop
	endif
	string device = monitorDeviceStr
	WAVE/Z tpStorage = GetTPStorage(device)
	if(!WaveExists(tpStorage))
		return 0 // TP not yet populated
	endif
	variable lastRow = DimSize(tpStorage, ROWS) - 1
	if(lastRow < 0)
		return 0
	endif
	variable targetV = DAG_GetNumericalValue(device, "setvar_DataAcq_AutoBiasV") // mV
	variable vRange = DAG_GetNumericalValue(device, "SetVar_DataAcq_AutoBiasVrange") // ± mV
	WAVE statusHS = DAG_GetChannelState(device, CHANNEL_TYPE_HEADSTAGE)
	variable i, allConverged = 1
	for(i = 0; i < NUM_HEADSTAGES; i += 1)
		if(!statusHS[i])
			continue
		endif
		if(tpStorage[lastRow][i][15] != I_CLAMP_MODE)
			continue
		endif
		variable vrest = tpStorage[lastRow][i][11]
		if(abs(vrest - targetV) > vRange)
			allConverged = 0
			break
		endif
	endfor
	if(!allConverged)
		return 0 // keep polling
	endif
	DQM_StopBackgroundTimer(device)
	TPM_StopTestPulseMultiDevice(device)
	RA_CounterMD(device)
	return 1 // stop background task
End

Questions for @t-b
Does this workflow have race conditions with RA/TP handling in MIES?
Should the monitor call both DQM_StopBackgroundTimer and TPM_StopTestPulseMultiDevice, or is there a preferred sequence?
Are there user-facing configs that should enable/disable this optimization?

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions