Skip to content

Commit

Permalink
Introduce Analysis functions V3
Browse files Browse the repository at this point in the history
The new analysis functions have the following features:
- Supports pre sweep event; called immediately before DAQ starts
- Uses the structure AnalysisFunction_V3 to pass data into analysis
  functions with additional members
- Allows to pass in arbitrary data via analysis function user
  parameters. Currently not with a GUI but only via
  WBP_AddAnalysisParameter. The user can enforce a list of parameters
  which must be present.
- One analysis function for all events.

Compatiblity notes:
- V1 and V2 analysis functions are still executed for existing stimsets.
  Changed and new stimsets must use V3 functions. See
  TestAnalysisFunction_V3() for an example V3 function.

New Textual Labnotebook Entries:
- "Pre Sweep function"
- "Generic function"
- "Function params"

Original-CommitID: 529219e6921ab3efad348a7b98e32d74b4bb37dc
  • Loading branch information
t-b committed Feb 1, 2018
1 parent a5486a3 commit 55ee1cc
Show file tree
Hide file tree
Showing 14 changed files with 518 additions and 141 deletions.
115 changes: 113 additions & 2 deletions Packages/MIES/MIES_AnalysisFunctionHelpers.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ Function/S AFH_GetAnalysisFunctions(versionBitMask)

string funcList, func
string funcListClean = ""
variable numEntries, i, valid_f1, valid_f2
variable numEntries, i, valid_f1, valid_f2, valid_f3

funcList = FunctionList("*", ";", "KIND:2,WIN:MIES_AnalysisFunctions.ipf")
funcList += FunctionList("*", ";", "KIND:2,WIN:MIES_AnalysisFunctions_PatchSeq.ipf")
Expand All @@ -300,15 +300,126 @@ Function/S AFH_GetAnalysisFunctions(versionBitMask)
// this allows to check if the signature of func is the same as the one of AF_PROTO_ANALYSIS_FUNC_V*
FUNCREF AF_PROTO_ANALYSIS_FUNC_V1 f1 = $func
FUNCREF AF_PROTO_ANALYSIS_FUNC_V2 f2 = $func
FUNCREF AF_PROTO_ANALYSIS_FUNC_V3 f3 = $func

valid_f1 = FuncRefIsAssigned(FuncRefInfo(f1))
valid_f2 = FuncRefIsAssigned(FuncRefInfo(f2))
valid_f3 = FuncRefIsAssigned(FuncRefInfo(f3))

if((valid_f1 && (versionBitMask & ANALYSIS_FUNCTION_VERSION_V1)) \
|| (valid_f2 && (versionBitMask & ANALYSIS_FUNCTION_VERSION_V2)))
|| (valid_f2 && (versionBitMask & ANALYSIS_FUNCTION_VERSION_V2)) \
|| (valid_f3 && (versionBitMask & ANALYSIS_FUNCTION_VERSION_V3)))
funcListClean = AddListItem(func, funcListClean, ";", Inf)
endif
endfor

return funcListClean
End

/// @brief Return the list of required analysis function
/// parameters as specified by the function `$func_GetParams`
///
/// @param func Analysis function `V3` which must be valid and existing
Function/S AFH_GetListOfReqAnalysisParams(func)
string func

FUNCREF AF_PROTO_PARAM_GETTER_V3 f = $(func + "_GetParams")

if(!FuncRefIsAssigned(FuncRefInfo(f))) // no such getter functions
return ""
endif

return f()
End

/// @defgroup AnalysisFunctionParameterHelpers Analysis Helper functions for dealing with user parameters

/// @brief Return a semicolon separated list of user parameters
///
/// @ingroup AnalysisFunctionParameterHelpers
/// @param params serialized parameters, usually just #AnalysisFunction_V3.params
Function/S AFH_GetListOfAnalysisParamNames(params)
string params

string entry, name
string list = ""
variable i, numEntries, pos

numEntries = ItemsInList(params, ",")
for(i = 0; i < numEntries; i += 1)
entry = StringFromList(i, params, ",")
pos = strsearch(entry, ":", 0)
ASSERT(pos != -1, "Invalid params format")
name = entry[0, pos - 1]
list = AddListItem(name, list, ";", Inf)
endfor

return list
End

/// @brief Return the type of the user parameter
///
/// @param name parameter name
/// @param params serialized parameters, usually just #AnalysisFunction_V3.params
///
/// @ingroup AnalysisFunctionParameterHelpers
/// @return one of @ref AnalysisFunctionParameterTypes
Function/S AFH_GetAnalysisParamType(name, params)
string name, params

string typeAndValue, type
variable pos

typeAndValue = StringByKey(name , params, ":", ",", 0)

pos = strsearch(typeAndValue, "=", 0)
ASSERT(pos != -1, "Invalid params format")
type = typeAndValue[0, pos - 1]
ASSERT(!IsEmpty(type) && WhichListItem(type, ANALYSIS_FUNCTION_PARAMS_TYPES) != -1, "Invalid type")

return typeAndValue[0, pos - 1]
End

/// @brief Return a numerical user parameter
///
/// @param name parameter name
/// @param params serialized parameters, usually just #AnalysisFunction_V3.params
/// @ingroup AnalysisFunctionParameterHelpers
Function AFH_GetAnalysisParamNumerical(name, params)
string name, params

return NumberByKey(name + ":variable", params, "=", ",", 0)
End

/// @brief Return a textual user parameter
///
/// @param name parameter name
/// @param params serialized parameters, usually just #AnalysisFunction_V3.params
/// @ingroup AnalysisFunctionParameterHelpers
Function/S AFH_GetAnalysisParamTextual(name, params)
string name, params

return StringByKey(name + ":string", params, "=", ",", 0)
End

/// @brief Return a numerical wave user parameter
///
/// @param name parameter name
/// @param params serialized parameters, usually just #AnalysisFunction_V3.params
/// @ingroup AnalysisFunctionParameterHelpers
Function/WAVE AFH_GetAnalysisParamWave(name, params)
string name, params

return ListToNumericWave(StringByKey(name + ":wave", params, "=", ",", 0), "|")
End

/// @brief Return a textual wave user parameter
///
/// @param name parameter name
/// @param params serialized parameters, usually just #AnalysisFunction_V3.params
/// @ingroup AnalysisFunctionParameterHelpers
Function/WAVE AFH_GetAnalysisParamTextWave(name, params)
string name, params

return ListToTextWave(StringByKey(name + ":textwave", params, "=", ",", 0), "|")
End
54 changes: 40 additions & 14 deletions Packages/MIES/MIES_AnalysisFunctionManagement.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ Function AFM_CallAnalysisFunctions(panelTitle, eventType)
string panelTitle
variable eventType

variable error, i, valid_f1, valid_f2, ret, DAC
variable realDataLength
variable error, i, valid_f1, valid_f2, valid_f3, ret, DAC, sweepsInSet
variable realDataLength, sweepNo
string func, setName, ctrl
struct AnalysisFunction_V3 s

WAVE GuiState = GetDA_EphysGuiStateNum(panelTitle)

Expand All @@ -28,6 +29,7 @@ Function AFM_CallAnalysisFunctions(panelTitle, eventType)

NVAR count = $GetCount(panelTitle)
NVAR stopCollectionPoint = $GetStopCollectionPoint(panelTitle)
NVAR fifoPosition = $GetFifoPosition(panelTitle)
WAVE statusHS = DAG_GetChannelState(panelTitle, CHANNEL_TYPE_HEADSTAGE)

WAVE/T analysisFunctions = GetAnalysisFunctionStorage(panelTitle)
Expand All @@ -44,29 +46,39 @@ Function AFM_CallAnalysisFunctions(panelTitle, eventType)
continue
endif

func = analysisFunctions[i][eventType]
// always prefer the generic event over the specialized ones
func = analysisFunctions[i][GENERIC_EVENT]

if(isEmpty(func))
func = analysisFunctions[i][eventType]
endif

if(isEmpty(func))
continue
endif

DAC = AFH_GetDACFromHeadstage(panelTitle, i)

ctrl = GetPanelControl(DAC, CHANNEL_TYPE_DAC, CHANNEL_CONTROL_WAVE)
// deliberately not using the GUI state wave
setName = GetPopupMenuString(panelTitle, ctrl)
sweepsInSet = IDX_NumberOfSweepsInSet(setName)

switch(eventType)
case PRE_DAQ_EVENT:
case MID_SWEEP_EVENT:
case PRE_SWEEP_EVENT:
case MID_SWEEP_EVENT: // fallthrough-by-design
sweepNo = DAG_GetNumericalValue(panelTitle, "SetVar_Sweep")
break
case POST_SWEEP_EVENT:
case POST_DAQ_EVENT:
// nothing to do
case POST_DAQ_EVENT: // fallthrough-by-design
sweepNo = DAG_GetNumericalValue(panelTitle, "SetVar_Sweep") - 1
break
case POST_SET_EVENT:
DAC = AFH_GetDACFromHeadstage(panelTitle, i)

ctrl = GetPanelControl(DAC, CHANNEL_TYPE_DAC, CHANNEL_CONTROL_WAVE)
// deliberately not using the GUI state wave
setName = GetPopupMenuString(panelTitle, ctrl)

if(mod(count + 1, IDX_NumberOfSweepsInSet(setName)) != 0)
if(mod(count + 1, sweepsInSet) != 0)
continue
endif
sweepNo = DAG_GetNumericalValue(panelTitle, "SetVar_Sweep") - 1
break
default:
ASSERT(0, "Invalid eventType")
Expand All @@ -75,12 +87,13 @@ Function AFM_CallAnalysisFunctions(panelTitle, eventType)

FUNCREF AF_PROTO_ANALYSIS_FUNC_V1 f1 = $func
FUNCREF AF_PROTO_ANALYSIS_FUNC_V2 f2 = $func
FUNCREF AF_PROTO_ANALYSIS_FUNC_V3 f3 = $func

valid_f1 = FuncRefIsAssigned(FuncRefInfo(f1))
valid_f2 = FuncRefIsAssigned(FuncRefInfo(f2))
valid_f3 = FuncRefIsAssigned(FuncRefInfo(f3))

// all functions are valid

WAVE ITCDataWave = GetITCDataWave(panelTitle)
SetWaveLock 1, ITCDataWave

Expand All @@ -90,6 +103,17 @@ Function AFM_CallAnalysisFunctions(panelTitle, eventType)
ret = f1(panelTitle, eventType, ITCDataWave, i); AbortOnRTE
elseif(valid_f2)
ret = f2(panelTitle, eventType, ITCDataWave, i, realDataLength); AbortOnRTE
elseif(valid_f3)
s.eventType = eventType
WAVE s.rawDACWave = ITCDataWave
s.headstage = i
s.lastValidRowIndex = realDataLength
s.lastKnownRowIndex = fifoPosition
s.sweepNo = sweepNo
s.sweepsInSet = sweepsInSet
s.params = analysisFunctions[i][ANALYSIS_FUNCTION_PARAMS]

ret = f3(panelTitle, s); AbortOnRTE
else
ASSERT(0, "impossible case")
endif
Expand Down Expand Up @@ -157,5 +181,7 @@ Function AFM_UpdateAnalysisFunctionWave(panelTitle)

analysisFunctions[i][j] = func
endfor

analysisFunctions[i][ANALYSIS_FUNCTION_PARAMS] = ExtractAnalysisFunctionParams(stimSet)
endfor
End
23 changes: 21 additions & 2 deletions Packages/MIES/MIES_AnalysisFunctionPrototypes.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
///
/// @sa MIES_AnalysisFunctions.ipf

/// @deprecated Use AF_PROTO_ANALYSIS_FUNC_V2() instead
/// @deprecated Use AF_PROTO_ANALYSIS_FUNC_V3() instead
///
/// @param panelTitle device
/// @param eventType eventType, one of @ref EVENT_TYPE_ANALYSIS_FUNCTIONS,
Expand All @@ -27,6 +27,8 @@ Function AF_PROTO_ANALYSIS_FUNC_V1(panelTitle, eventType, ITCDataWave, headStage
variable headstage
End

/// @deprecated Use AF_PROTO_ANALYSIS_FUNC_V3() instead
///
/// @param panelTitle device
/// @param eventType eventType, one of @ref EVENT_TYPE_ANALYSIS_FUNCTIONS,
/// always compare `eventType` with the constants, never use the current numerical value directly
Expand All @@ -35,7 +37,7 @@ End
/// @param realDataLength number of rows in `ITCDataWave` with data, the total number of rows in `ITCDataWave` might be
/// higher due to alignment requirements of the data acquisition hardware. `NaN` for #PRE_DAQ_EVENT events.
///
/// @return see @ref AnalysisFunctionEventDescriptionTable
/// @return see @ref AnalysisFunction_V3DescriptionTable
Function AF_PROTO_ANALYSIS_FUNC_V2(panelTitle, eventType, ITCDataWave, headStage, realDataLength)
string panelTitle
variable eventType
Expand All @@ -44,3 +46,20 @@ Function AF_PROTO_ANALYSIS_FUNC_V2(panelTitle, eventType, ITCDataWave, headStage

return 0
End

/// @param panelTitle device
/// @param s analysis event structure
///
/// @return see @ref AnalysisFunction_V3DescriptionTable
Function AF_PROTO_ANALYSIS_FUNC_V3(panelTitle, s)
string panelTitle
STRUCT AnalysisFunction_V3 &s

return 0
End

/// @brief Prototype function for the user supplied parameter getter functions
///
Function/S AF_PROTO_PARAM_GETTER_V3()

End
Loading

0 comments on commit 55ee1cc

Please sign in to comment.