Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate changed stimsets better #1908

Merged
merged 12 commits into from
Oct 11, 2023
7 changes: 4 additions & 3 deletions Packages/MIES/MIES_DAEphys.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -1521,7 +1521,7 @@ Function DAP_PopMenuChkProc_StimSetList(pa) : PopupMenuControl
// is not yet reflected in the user data
list = GetUserData(device, ctrl, USER_DATA_MENU_EXP)
if(FindListItem(stimSet, list) == -1)
DAP_UpdateDaEphysStimulusSetPopups()
WB_UpdateChangedStimsets()
endif
endif

Expand Down Expand Up @@ -4456,7 +4456,7 @@ Function DAP_LockDevice(string win)
DAP_UpdateDAQControls(deviceLocked, REASON_STIMSET_CHANGE | REASON_HEADSTAGE_CHANGE)
// create the amplifier settings waves
GetAmplifierParamStorageWave(deviceLocked)
DAP_UpdateDaEphysStimulusSetPopups(device=deviceLocked)
WB_UpdateChangedStimsets(device=deviceLocked)
DAP_UnlockCommentNotebook(deviceLocked)
DAP_ToggleAcquisitionButton(deviceLocked, DATA_ACQ_BUTTON_TO_DAQ)
SI_CalculateMinSampInterval(deviceLocked, DATA_ACQUISITION_MODE)
Expand Down Expand Up @@ -5339,6 +5339,7 @@ Function DAP_DeleteStimulusSet(string setName, [string device])
if(ParamIsDefault(device))
WB_KillParameterWaves(setName)
WB_KillStimset(setName)
WB_UpdateChangedStimsets()
return NaN
endif

Expand All @@ -5351,7 +5352,7 @@ Function DAP_DeleteStimulusSet(string setName, [string device])
WB_KillParameterWaves(setName)
WB_KillStimset(setName)

DAP_UpdateDaEphysStimulusSetPopups(device = device)
WB_UpdateChangedStimsets(device = device)
End

/// @brief Write all TP settings from the data acquisition/settings tab to the settings wave
Expand Down
2 changes: 1 addition & 1 deletion Packages/MIES/MIES_DataBrowser_Macro.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ Window DataBrowser() : Graph
SetVariable setvar_pulseAver_startPulse,limits={0,inf,1},value=_NUM:0
CheckBox check_pulseAver_multGraphs,pos={234.00,165.00},size={121.00,15.00},disable=1,proc=PA_CheckProc_Common
CheckBox check_pulseAver_multGraphs,title="Use multiple graphs"
CheckBox check_pulseAver_multGraphs,help={"Show the single pulses in multiple graphs or only one graph with mutiple axis."}
CheckBox check_pulseAver_multGraphs,help={"Show the single pulses in multiple graphs or only one graph with multiple axis."}
CheckBox check_pulseAver_multGraphs,userdata(tabnum)="4"
CheckBox check_pulseAver_multGraphs,userdata(tabcontrol)="Settings"
CheckBox check_pulseAver_multGraphs,userdata(ResizeControlsInfo)=A"!!,H%!!#A4!!#@V!!#<(z!!#`-A7TLfzzzzzzzzzzzzzz!!#r+D.OhkBk2=!z"
Expand Down
2 changes: 1 addition & 1 deletion Packages/MIES/MIES_NeuroDataWithoutBorders.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -1634,7 +1634,7 @@ Function NWB_LoadAllStimsets([overwrite, fileName, loadOnlyBuiltins])
HDF5CloseGroup/Z groupID
H5_CloseFile(fileID)

DAP_UpdateDaEphysStimulusSetPopups()
WB_UpdateChangedStimsets()

LOG_AddEntry(PACKAGE_MIES, "end")

Expand Down
58 changes: 40 additions & 18 deletions Packages/MIES/MIES_Utilities.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ End
/// @param upsampleFactor positive non-zero integer by which the wave should
/// be upsampled
/// @param mode decimation mode, one of @ref DECIMATION_BY_OMISSION,
/// @ref DECIMATION_BY_AVERAGING
/// @ref DECIMATION_BY_AVERAGING
/// or @ref DECIMATION_BY_SMOOTHING.
/// @param winFunction Windowing function for @ref DECIMATION_BY_SMOOTHING mode,
/// must be one of @ref FFT_WINF.
Expand Down Expand Up @@ -2116,13 +2116,14 @@ threadsafe Function/S RemoveEndingRegExp(str, endingRegExp)
string str, endingRegExp

string endStr
variable err

if(isEmpty(str) || isEmpty(endingRegExp))
return str
endif

SplitString/E=("(" + endingRegExp + ")$") str, endStr
ASSERT_TS(V_flag == 0 || V_flag == 1, "Unexpected number of matches")
SplitString/E=("(" + endingRegExp + ")$") str, endStr; err = GetRTError(1)
ASSERT_TS((V_flag == 0 || V_flag == 1) && err == 0, "Unexpected number of matches or invalid regex")

return RemoveEnding(str, endStr)
End
Expand Down Expand Up @@ -2150,20 +2151,38 @@ End
///
/// @return 1 if word was found in str and word was not "". 0 if not.
Function SearchWordInString(string str, string word, [string &prefix, string &suffix])
WAVE/Z/T wv = SearchStringBase(str, "(.*)\\b\\Q" + word + "\\E\\b(.*)")
if(!WaveExists(wv))
return 0

string prefixParam, suffixParam
variable ret

[ret, prefixParam, suffixParam] = SearchRegexInString(str, "\\b\\Q" + word + "\\E\\b")

if(!ret)
return ret
endif

if(!ParamIsDefault(prefix))
prefix = wv[0]
prefix = prefixParam
endif

if(!ParamIsDefault(suffix))
suffix = wv[1]
suffix = suffixParam
endif

return 1
return ret
End

static Function [variable ret, string prefix, string suffix] SearchRegexInString(string str, string regex)

ASSERT(IsValidRegexp(regex), "Empty regex")

WAVE/Z/T wv = SearchStringBase(str, "(.*)" + regex + "(.*)")

if(!WaveExists(wv))
return [0, "", ""]
endif

return [1, wv[0], wv[1]]
End

/// @brief More advanced version of SplitString
Expand Down Expand Up @@ -4027,24 +4046,27 @@ Function/S SortAxisList(graph, list)
return TextWaveToList(axisListWave, ";")
End

/// @brief Replaces all occurences of the string `word`, treated as regexp word,
/// in `str` with `replacement`. Does not ignore case.
Function/S ReplaceWordInString(word, str, replacement)
string word, str, replacement
Function/S ReplaceWordInString(string word, string str, string replacement)

ASSERT(!IsEmpty(word), "Empty regex")

variable ret
string result, prefix, suffix
ASSERT(!IsEmpty(word), "Empty word")

if(!cmpstr(word, replacement, 0))
return str
endif

return ReplaceRegexInString("\\b\\Q" + word + "\\E\\b", str, replacement)
End

/// @brief Replaces all occurences of the regular expression `regex` in `str` with `replacement`
Function/S ReplaceRegexInString(string regex, string str, string replacement)

variable ret
string result, prefix, suffix

result = str

for(;;)
ret = SearchWordInString(result, word, prefix = prefix, suffix = suffix)
[ret, prefix, suffix] = SearchRegexInString(result, regex)

if(!ret)
break
Expand Down
69 changes: 40 additions & 29 deletions Packages/MIES/MIES_WaveBuilder.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -1937,12 +1937,9 @@ static Function/WAVE WB_FillWaveFromFormula(formula, channelType, sweep)
STRUCT FormulaProperties fp
string shorthandFormula

// update shorthand -> stimset mapping
WB_UpdateEpochCombineList(channelType)
shorthandFormula = WB_FormulaSwitchToShorthand(channelType, formula)

shorthandFormula = WB_FormulaSwitchToShorthand(formula)

if(WB_ParseCombinerFormula(shorthandFormula, sweep, fp))
if(WB_ParseCombinerFormula(channelType, shorthandFormula, sweep, fp))
return $""
endif

Expand Down Expand Up @@ -1972,7 +1969,7 @@ End
///
/// The rows are sorted by creationDate of the WP/stimset wave to try to keep
/// the shorthands constants even when new stimsets are added.
Function WB_UpdateEpochCombineList(variable channelType)
Function WB_UpdateEpochCombineList(WAVE/T epochCombineList, variable channelType)
string list, setPath, setParamPath, entry
variable numEntries, i

Expand Down Expand Up @@ -2006,7 +2003,6 @@ Function WB_UpdateEpochCombineList(variable channelType)

Sort creationDates, stimsets

Wave/T epochCombineList = GetWBEpochCombineList()
Redimension/N=(numEntries, -1) epochCombineList

epochCombineList[][%StimSet] = stimsets[p]
Expand Down Expand Up @@ -2035,16 +2031,14 @@ End

/// @brief Parse the formula from the epoch type `Combine`
///
/// @param[in] formula math formula to execute, all operators which Igor can grok are allowed
/// @param sweep current sweep (aka step)
/// @param[out] fp parsed formula structure, with shorthands replaced by stimsets,
/// empty on parse error, ready to be executed by WB_FillWaveFromFormula()
/// @param[in] channelType One of CHANNEL_TYPE_DA or CHANNEL_TYPE_TTL
/// @param[in] formula math formula to execute, all operators which Igor can grok are allowed
/// @param[in] sweep current sweep (aka step)
/// @param[out] fp parsed formula structure, with shorthands replaced by stimsets,
/// empty on parse error, ready to be executed by WB_FillWaveFromFormula()
///
/// @returns 0 on success, 1 on parse errors (currently not many are found)
Function WB_ParseCombinerFormula(formula, sweep, fp)
string formula
variable sweep
struct FormulaProperties &fp
Function WB_ParseCombinerFormula(variable channelType, string formula, variable sweep, STRUCT FormulaProperties &fp)

string dependentStimsets
variable i, numStimsets
Expand All @@ -2054,7 +2048,7 @@ Function WB_ParseCombinerFormula(formula, sweep, fp)

InitFormulaProperties(fp)
InitFormulaProperties(trans)
WB_FormulaSwitchToStimset(formula, trans)
WB_FormulaSwitchToStimset(channelType, formula, trans)

// look for shorthand-like strings not referring to existing stimsets
if(GrepString(trans.formula, "\\b[A-Z][0-9]*\\b"))
Expand Down Expand Up @@ -2100,10 +2094,7 @@ Function WB_ParseCombinerFormula(formula, sweep, fp)
End

/// @brief Replace shorthands with the real stimset names suffixed with `?`
Function WB_FormulaSwitchToStimset(formula, fp)
string formula
struct FormulaProperties &fp

Function WB_FormulaSwitchToStimset(variable channelType, string formula, STRUCT FormulaProperties &fp)
string stimset, shorthand, stimsetSpec, prefix, suffix
variable numSets, i, stimsetFound

Expand All @@ -2113,7 +2104,7 @@ Function WB_FormulaSwitchToStimset(formula, fp)
return NaN
endif

WAVE/T epochCombineList = GetWBEpochCombineList()
WAVE/T epochCombineList = GetWBEpochCombineList(channeltype)

formula = UpperStr(formula)

Expand All @@ -2122,7 +2113,7 @@ Function WB_FormulaSwitchToStimset(formula, fp)
// iterate the stimset list from bottom to top, so that we replace first the shorthands
// with numeric prefix and only later on the ones without
numSets = DimSize(epochCombineList, ROWS)
for(i = numSets - 1; i >= 0; i -= 1)
for(i = numSets - 1; i >= 0 && numSets > 0; i -= 1)
shorthand = epochCombineList[i][%Shorthand]
stimset = epochCombineList[i][%stimset]
stimsetSpec = LowerStr(stimset) + "?"
Expand Down Expand Up @@ -2164,24 +2155,24 @@ static Function WB_PrepareFormulaForExecute(fp, sweep)
End

/// @brief Replace all stimsets suffixed with `?` by their shorthands
Function/S WB_FormulaSwitchToShorthand(formula)
string formula
Function/S WB_FormulaSwitchToShorthand(variable channelType, string formula)

variable numSets, i
string stimset, shorthand
string stimset, shorthand, regex

if(isEmpty(formula))
return ""
endif

WAVE/T epochCombineList = GetWBEpochCombineList()
WAVE/T epochCombineList = GetWBEpochCombineList(channelType)

numSets = DimSize(epochCombineList, ROWS)
for(i = 0; i < numSets; i += 1)
shorthand = epochCombineList[i][%Shorthand]
stimset = epochCombineList[i][%stimset]

formula = ReplaceString(stimset + "?", formula, shorthand)
regex = "\\b\\Q" + LowerStr(stimset) + "\\E\\b\?"
formula = ReplaceRegexInString(regex, formula, shorthand)
endfor

return formula
Expand Down Expand Up @@ -2680,8 +2671,7 @@ Function/S WB_SaveStimSet(string baseName, variable stimulusType, WAVE SegWvType
ASSERT(WaveExists(stimset), "Could not recreate stimset")

// propagate the existence of the new set
DAP_UpdateDaEphysStimulusSetPopups()
WB_UpdateEpochCombineList(stimulusType)
WB_UpdateChangedStimsets(stimulusType = stimulusType)

return setName
End
Expand Down Expand Up @@ -2816,3 +2806,24 @@ Function WB_MakeStimsetThirdParty(string setName)
KillOrMoveToTrash(wv=WPT)
KillOrMoveToTrash(wv=SegWvType)
End

/// @brief Propagate added/removed stimsets to DA_Ephys panels and our epoch combine list
Function WB_UpdateChangedStimsets([string device, variable stimulusType])

if(ParamIsDefault(device))
DAP_UpdateDaEphysStimulusSetPopups()
else
DAP_UpdateDaEphysStimulusSetPopups(device = device)
endif

if(ParamIsDefault(stimulusType))
WAVE/T epochCombineList = GetWBEpochCombineList(CHANNEL_TYPE_DAC)
WB_UpdateEpochCombineList(epochCombineList, CHANNEL_TYPE_DAC)

WAVE/T epochCombineList = GetWBEpochCombineList(CHANNEL_TYPE_TTL)
WB_UpdateEpochCombineList(epochCombineList, CHANNEL_TYPE_TTL)
else
WAVE/T epochCombineList = GetWBEpochCombineList(stimulusType)
WB_UpdateEpochCombineList(epochCombineList, stimulusType)
endif
End
22 changes: 14 additions & 8 deletions Packages/MIES/MIES_WaveBuilderPanel.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ Function/S WBP_CreateWaveBuilderPanel()

WBP_ClearFolders()

WB_UpdateChangedStimsets()

Execute "WaveBuilder()"
ListBox listbox_combineEpochMap, listWave=GetWBEpochCombineList()
ListBox listbox_combineEpochMap, listWave=GetWBEpochCombineList(WBP_GetStimulusType())
AddVersionToPanel(panel, WAVEBUILDER_PANEL_VERSION)

NVAR JSONid = $GetSettingsJSONid()
Expand Down Expand Up @@ -403,9 +405,6 @@ static Function WBP_UpdatePanelIfAllowed()
SetSetVariable(panel, "SetVar_WaveBuilder_P8", maxDuration)
endif
break
case EPOCH_TYPE_COMBINE:
WB_UpdateEpochCombineList(WBP_GetStimulusType())
break
default:
// nothing to do
break
Expand Down Expand Up @@ -834,6 +833,8 @@ static Function WBP_ChangeWaveType()
ASSERT(0, "Unknown stimulus type")
endif

ListBox listbox_combineEpochMap, win=$panel, listWave=GetWBEpochCombineList(WBP_GetStimulusType())

WBP_UpdatePanelIfAllowed()
End

Expand Down Expand Up @@ -1426,7 +1427,7 @@ Function WBP_SetVarCombineEpochFormula(sva) : SetVariableControl

struct FormulaProperties fp
string win, formula
variable currentEpoch, lastSweep
variable currentEpoch, lastSweep, channelType

switch(sva.eventCode)
case 1: // mouse up
Expand All @@ -1436,10 +1437,11 @@ Function WBP_SetVarCombineEpochFormula(sva) : SetVariableControl
formula = sva.sval

WAVE/T WPT = GetWaveBuilderWaveTextParam()
channelType = WBP_GetStimulusType()

lastSweep = GetSetVariable(win, "SetVar_WB_SweepCount_S101") - 1

if(WB_ParseCombinerFormula(formula, lastSweep, fp))
if(WB_ParseCombinerFormula(channelType, formula, lastSweep, fp))
break
endif

Expand Down Expand Up @@ -1469,11 +1471,13 @@ static Function/S WBP_TranslateControlContents(control, direction, data)
strswitch(control)
case "setvar_combine_formula_T6":
if(direction == FROM_PANEL_TO_WAVE)
variable channelType = WBP_GetStimulusType()

struct FormulaProperties fp
WB_FormulaSwitchToStimset(data, fp)
WB_FormulaSwitchToStimset(channelType, data, fp)
return fp.formula
elseif(direction == FROM_WAVE_TO_PANEL)
return WB_FormulaSwitchToShorthand(data)
return WB_FormulaSwitchToShorthand(channelType, data)
endif
break
default:
Expand Down Expand Up @@ -2151,6 +2155,8 @@ static Function/WAVE WBP_ListControlsPerStimulusType(variable epochType)
// additional entries which are not covered by the usual naming scheme
if(epochType == EPOCH_TYPE_CUSTOM)
Make/FREE/T additional = {"Custom epoch wave name"}
elseif(epochType == EPOCH_TYPE_COMBINE)
Make/FREE/T additional = {"Combine epoch formula version"}
else
Make/FREE/T/N=(0) additional
endif
Expand Down
Loading