Skip to content

Commit d6f3575

Browse files
authored
Merge pull request #1037 from AllenInstitute/bugfix/1037-dashboard-chirp-fail-message
Fix failure message gathering in the analysis function dashboard
2 parents e29e3d3 + b428d45 commit d6f3575

File tree

2 files changed

+168
-80
lines changed

2 files changed

+168
-80
lines changed

Packages/MIES/MIES_AnalysisFunctions_Dashboard.ipf

+167-79
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Function AD_Update(win)
6767
if(numEntries > 0)
6868
selWave[][][%foreColors] = AD_GetColorForResultMessage(listWave[p][%Result])
6969

70-
helpWave[] = "Result: " + listWave[p][%Result]
70+
helpWave[] = "Result:\r" + listWave[p][%Result]
7171

7272
EnableControls(mainPanel, "check_BrowserSettings_DB_Failed;check_BrowserSettings_DB_Passed")
7373
else
@@ -84,9 +84,6 @@ static Function/S AD_GetResultMessage(variable anaFuncType, variable passed, WAV
8484
return "Pass"
8585
endif
8686

87-
// PSQ_DA, PSQ_RB, PSQ_RA, PSQ_SP, PSQ_CR
88-
// PSQ_FMT_LBN_BL_QC_PASS
89-
9087
// MSQ_DA
9188
// - always passes
9289

@@ -101,16 +98,21 @@ static Function/S AD_GetResultMessage(variable anaFuncType, variable passed, WAV
10198
// - Not enough sweeps
10299

103100
// PSQ_CR
101+
// - baseline QC
104102
// - needs at least PSQ_CR_NUM_SWEEPS_PASS passing sweeps with the same to-full-pA rounded DAScale
103+
// - spike found while none expected (optional)
105104

106105
// PSQ_DA
106+
// - baseline QC
107107
// - needs at least $NUM_DA_SCALES passing sweeps
108108
// and for supra mode if the FinalSlopePercent parameter is present this has to be reached as well
109109

110110
// PSQ_RA
111+
// - baseline QC
111112
// - needs at least PSQ_RA_NUM_SWEEPS_PASS passing sweeps
112113

113114
// PSQ_RB
115+
// - baseline QC
114116
// - Difference to initial DAScale larger than 60pA?
115117
// - Not enough sweeps
116118

@@ -124,13 +126,13 @@ static Function/S AD_GetResultMessage(variable anaFuncType, variable passed, WAV
124126
case MSQ_FAST_RHEO_EST:
125127
return AD_GetFastRheoEstFailMsg(numericalValues, sweepNo, headstage)
126128
case PSQ_CHIRP:
127-
return AD_GetChirpFailMsg(numericalValues, sweepNo, headstage)
129+
return AD_GetChirpFailMsg(numericalValues, textualValues, sweepNo, headstage)
128130
case PSQ_DA_SCALE:
129131
return AD_GetDaScaleFailMsg(numericalValues, textualValues, sweepNo, headstage)
130132
case PSQ_RAMP:
131-
return AD_GetRampFailMsg(numericalValues, sweepNo, headstage)
133+
return AD_GetRampFailMsg(numericalValues, textualValues, sweepNo, headstage)
132134
case PSQ_RHEOBASE:
133-
return AD_GetRheobaseFailMsg(numericalValues, sweepNo, headstage)
135+
return AD_GetRheobaseFailMsg(numericalValues, textualValues, sweepNo, headstage)
134136
case PSQ_SQUARE_PULSE:
135137
return AD_GetSquarePulseFailMsg(numericalValues, sweepNo, headstage)
136138
case SC_SPIKE_CONTROL:
@@ -390,8 +392,8 @@ static Function/S AD_GetDAScaleFailMsg(numericalValues, textualValues, sweepNo,
390392
ASSERT(WaveExists(DASCales), "analysis function parameters don't have a DAScales entry")
391393
numRequiredPasses = DimSize(DAScales, ROWS)
392394

393-
if(numPasses < numRequiredPasses)
394-
sprintf msg, "Failure as we ran out of sweeps (%d passed but we needed %d)", numPasses, numRequiredPasses
395+
msg = AD_GetPerSweepFailMessage(PSQ_DA_SCALE, numericalValues, textualValues, sweepNo, headstage, numRequiredPasses = numRequiredPasses)
396+
if(!IsEmpty(msg))
395397
return msg
396398
endif
397399

@@ -417,70 +419,28 @@ End
417419
/// @brief Return an appropriate error message for why #PSQ_RAMP failed
418420
///
419421
/// @param numericalValues Numerical labnotebook
422+
/// @param textualValues Textual labnotebook
420423
/// @param sweepNo Sweep number
421424
/// @param headstage Headstage
422-
static Function/S AD_GetRampFailMsg(numericalValues, sweepNo, headstage)
423-
variable sweepNo
424-
WAVE numericalValues
425-
variable headstage
426-
427-
string msg
428-
variable numPasses
429-
430-
msg = AD_GetBaselineFailMsg(PSQ_RAMP, numericalValues, sweepNo, headstage)
431-
432-
if(!IsEmpty(msg))
433-
return msg
434-
endif
435-
436-
numPasses = PSQ_NumPassesInSet(numericalValues, PSQ_RAMP, sweepNo, headstage)
437-
if(numPasses < PSQ_RA_NUM_SWEEPS_PASS)
438-
sprintf msg, "Failure as we ran out of sweeps (%d passed but we needed %d)", numPasses, PSQ_RA_NUM_SWEEPS_PASS
439-
return msg
440-
endif
441-
442-
BUG("Unknown reason for failure")
443-
return "Failure"
425+
static Function/S AD_GetRampFailMsg(WAVE numericalValues, WAVE/T textualValues, variable sweepNo, variable headstage)
426+
return AD_GetPerSweepFailMessage(PSQ_RAMP, numericalValues, textualValues, sweepNo, headstage, numRequiredPasses = PSQ_RA_NUM_SWEEPS_PASS)
444427
End
445428

446429
/// @brief Return an appropriate error message for why #PSQ_RHEOBASE failed
447430
///
448431
/// @param numericalValues Numerical labnotebook
432+
/// @param textualValues Textual labnotebook
449433
/// @param sweepNo Sweep number
450434
/// @param headstage Headstage
451-
static Function/S AD_GetRheobaseFailMsg(numericalValues, sweepNo, headstage)
452-
variable sweepNo
453-
WAVE numericalValues
454-
variable headstage
455-
456-
string key, msg
457-
458-
msg = AD_GetBaselineFailMsg(PSQ_RHEOBASE, numericalValues, sweepNo, headstage)
459-
460-
if(!IsEmpty(msg))
461-
return msg
462-
endif
435+
static Function/S AD_GetRheobaseFailMsg(WAVE numericalValues, WAVE/T textualValues, variable sweepNo, variable headstage)
436+
string key, prefix, msg
463437

464-
key = CreateAnaFuncLBNKey(PSQ_RHEOBASE, PSQ_FMT_LBN_RB_DASCALE_EXC, query = 1)
465-
WAVE/Z daScaleExc = GetLastSettingEachSCI(numericalValues, sweepNo, key, headstage, UNKNOWN_MODE)
466-
ASSERT(WaveExists(daScaleExc), "Missing DAScale exceeded LBN entry")
467-
468-
if(AD_LabnotebookEntryExistsAndIsTrue(daScaleExc))
469-
return "Max DA scale exceeded failure"
470-
endif
471-
472-
key = CreateAnaFuncLBNKey(PSQ_RHEOBASE, PSQ_FMT_LBN_RB_LIMITED_RES, query = 1)
473-
WAVE/Z limitedResolution = GetLastSettingEachSCI(numericalValues, sweepNo, key, headstage, UNKNOWN_MODE)
474-
ASSERT(WaveExists(limitedResolution), "Missing limited resolution labnotebook entry")
475-
476-
if(AD_LabnotebookEntryExistsAndIsTrue(limitedResolution))
477-
return "Failure due to limited resolution"
478-
endif
438+
prefix = AD_GetPerSweepFailMessage(PSQ_RHEOBASE, numericalValues, textualValues, sweepNo, headstage)
479439

480440
key = CreateAnaFuncLBNKey(PSQ_RHEOBASE, PSQ_FMT_LBN_SPIKE_DETECT, query = 1)
481441
WAVE/Z spikeDetect = GetLastSettingEachSCI(numericalValues, sweepNo, key, headstage, UNKNOWN_MODE)
482442

483-
sprintf msg, "Failure as we were not able to find the correct on/off spike pattern (%s)", RemoveEnding(NumericWaveToList(spikeDetect, ", ", format="%g"), ", ")
443+
sprintf msg, "%s\rWe were not able to find the correct on/off spike pattern (%s)", prefix, RemoveEnding(NumericWaveToList(spikeDetect, ", ", format="%g"), ", ")
484444
return msg
485445
End
486446

@@ -515,41 +475,33 @@ End
515475
/// @brief Return an appropriate error message for why #PSQ_CHIRP failed
516476
///
517477
/// @param numericalValues Numerical labnotebook
478+
/// @param textualValues Textual labnotebook
518479
/// @param sweepNo Sweep number
519480
/// @param headstage Headstage
520-
static Function/S AD_GetChirpFailMsg(numericalValues, sweepNo, headstage)
521-
WAVE numericalValues
522-
variable sweepNo
523-
variable headstage
524-
481+
static Function/S AD_GetChirpFailMsg(WAVE numericalValues,WAVE/T textualValues, variable sweepNo, variable headstage)
525482
string key, msg, str
526483
string text = ""
527-
variable numPasses, i, numEntries, setPassed, maxOccurences
484+
variable i, numSweeps, setPassed, maxOccurences
528485

529-
msg = AD_GetBaselineFailMsg(PSQ_CHIRP, numericalValues, sweepNo, headstage)
486+
msg = AD_GetPerSweepFailMessage(PSQ_CHIRP, numericalValues, textualValues, sweepNo, headstage, numRequiredPasses = PSQ_CR_NUM_SWEEPS_PASS)
530487

531488
if(!IsEmpty(msg))
532489
return msg
533490
endif
534491

535-
numPasses = PSQ_NumPassesInSet(numericalValues, PSQ_CHIRP, sweepNo, headstage)
536-
if(numPasses < PSQ_CR_NUM_SWEEPS_PASS)
537-
sprintf msg, "Failure as we ran out of sweeps (%d passed but we needed %d)", numPasses, PSQ_CR_NUM_SWEEPS_PASS
538-
return msg
539-
endif
540-
492+
// all sweeps passed, but the set did not pass
541493
[setPassed, maxOccurences] = PSQ_CR_SetHasPassed(numericalValues, sweepNo, headstage)
542494

543495
if(!setPassed)
544-
545496
key = CreateAnaFuncLBNKey(PSQ_CHIRP, PSQ_FMT_LBN_SWEEP_PASS, query = 1)
546497
WAVE sweepPass = GetLastSettingIndepEachSCI(numericalValues, sweepNo, key, headstage, UNKNOWN_MODE)
547498

548499
WAVE DAScales = GetLastSettingEachSCI(numericalValues, sweepNo, STIMSET_SCALE_FACTOR_KEY, headstage, DATA_ACQUISITION_MODE)
549500
ASSERT(DimSize(sweepPass, ROWS) == DimSize(DAScales, ROWS), "Unexpected sizes")
550501

551-
for(i = 0; i < numEntries; i += 1)
552-
sprintf str, "%g:%d, ", DAScales[i], sweepPass[i]
502+
numSweeps = DimSize(sweepPass, ROWS)
503+
for(i = 0; i < numSweeps; i += 1)
504+
sprintf str, "%g:%s, ", DAScales[i], ToPassFail(sweepPass[i])
553505

554506
text += str
555507
endfor
@@ -564,7 +516,7 @@ static Function/S AD_GetChirpFailMsg(numericalValues, sweepNo, headstage)
564516
return "Failure"
565517
End
566518

567-
/// @brief Return an appropriate error message if the baseline QC failed, or an empty string otherwise
519+
/// @brief Return an appropriate error message if the baseline QC failed for the given sweep, or an empty string otherwise
568520
///
569521
/// @param anaFuncType One of @ref PatchSeqAnalysisFunctionTypes
570522
/// @param numericalValues Numerical labnotebook
@@ -584,7 +536,7 @@ static Function/S AD_GetBaselineFailMsg(anaFuncType, numericalValues, sweepNo, h
584536
case PSQ_RAMP:
585537
case PSQ_CHIRP:
586538
key = CreateAnaFuncLBNKey(anaFuncType, PSQ_FMT_LBN_BL_QC_PASS, query = 1)
587-
WAVE/Z baselineQC = GetLastSettingSCI(numericalValues, sweepNo, key, headstage, UNKNOWN_MODE)
539+
WAVE/Z baselineQC = GetLastSetting(numericalValues, sweepNo, key, UNKNOWN_MODE)
588540

589541
if(anaFuncType == PSQ_CHIRP && !WaveExists(baselineQC))
590542
// we did not evaluate the baseline completely but aborted earlier
@@ -596,15 +548,15 @@ static Function/S AD_GetBaselineFailMsg(anaFuncType, numericalValues, sweepNo, h
596548
if(!baselineQC[headstage])
597549
for(i = 0; ;i += 1)
598550
key = CreateAnaFuncLBNKey(anaFuncType, PSQ_FMT_LBN_CHUNK_PASS, query = 1, chunk = i)
599-
chunkQC = GetLastSettingIndepSCI(numericalValues, sweepNo, key, headstage, UNKNOWN_MODE)
551+
chunkQC = GetLastSettingIndep(numericalValues, sweepNo, key, UNKNOWN_MODE)
600552

601553
if(IsNaN(chunkQC))
602554
// no more chunks
603555
break
604556
endif
605557

606558
if(!chunkQC)
607-
sprintf msg, "Failed due to Baseline QC failure in chunk %d", i
559+
sprintf msg, "Baseline QC failure in chunk %d", i
608560
return msg
609561
endif
610562
endfor
@@ -617,6 +569,142 @@ static Function/S AD_GetBaselineFailMsg(anaFuncType, numericalValues, sweepNo, h
617569
return ""
618570
End
619571

572+
/// @brief Gather per sweep failure information for some analysis function types
573+
///
574+
/// @param anaFuncType analysis function type
575+
/// @param numericalValues numerical labnotebook
576+
/// @param textualValues textual labnotebook
577+
/// @param refSweepNo reference sweep number
578+
/// @param headstage headstage
579+
/// @param numRequiredPasses [optional, defaults to off] allows to determine the set failure state by not having reached enough passing sets
580+
///
581+
/// @sa AD_GetResultMessage()
582+
static Function/S AD_GetPerSweepFailMessage(variable anaFuncType, WAVE numericalValues, WAVE/T textualValues, variable refSweepNo, variable headstage, [variable numRequiredPasses])
583+
string key, msg, str
584+
string text = ""
585+
variable numPasses, i, numSweeps, sweepNo, boundsAction, spikeCheck
586+
string perSweepFailedMessage = ""
587+
588+
if(!ParamIsDefault(numRequiredPasses))
589+
numPasses = PSQ_NumPassesInSet(numericalValues, anaFuncType, refSweepNo, headstage)
590+
591+
if(numPasses >= numRequiredPasses)
592+
return ""
593+
endif
594+
endif
595+
596+
key = CreateAnaFuncLBNKey(anaFuncType, PSQ_FMT_LBN_SWEEP_PASS, query = 1)
597+
WAVE/Z sweepPass = GetLastSettingIndepEachSCI(numericalValues, refSweepNo, key, headstage, UNKNOWN_MODE)
598+
599+
WAVE sweeps = AFH_GetSweepsFromSameSCI(numericalValues, refSweepNo, headstage)
600+
numSweeps = DimSize(sweeps, ROWS)
601+
602+
for(i = 0; i < numSweeps; i += 1)
603+
sweepNo = sweeps[i]
604+
text = ""
605+
606+
if(WaveExists(sweepPass) && sweepPass[i])
607+
sprintf text, "Sweep %d passed", sweeps[i]
608+
perSweepFailedMessage += text + "\r"
609+
continue
610+
endif
611+
612+
switch(anaFuncType)
613+
case PSQ_CHIRP:
614+
msg = AD_GetBaselineFailMsg(PSQ_CHIRP, numericalValues, sweepNo, headstage)
615+
616+
if(!IsEmpty(msg))
617+
sprintf text, "Sweep %d failed: %s", sweepNo, msg
618+
break
619+
endif
620+
621+
key = CreateAnaFuncLBNKey(PSQ_CHIRP, PSQ_FMT_LBN_CR_BOUNDS_ACTION, query = 1)
622+
boundsAction = GetLastSettingIndep(numericalValues, sweepNo, key, UNKNOWN_MODE)
623+
624+
if(IsFinite(boundsAction) && boundsAction != PSQ_CR_PASS)
625+
sprintf text, "Sweep %d failed: bounds action %s", sweepNo, PSQ_CR_BoundsActionToString(boundsAction)
626+
break
627+
endif
628+
629+
key = CreateAnaFuncLBNKey(PSQ_CHIRP, PSQ_FMT_LBN_CR_SPIKE_CHECK, query = 1)
630+
spikeCheck = GetLastSettingIndepSCI(numericalValues, sweepNo, key, headstage, UNKNOWN_MODE)
631+
632+
if(spikeCheck)
633+
key = CreateAnaFuncLBNKey(PSQ_CHIRP, PSQ_FMT_LBN_CR_SPIKE_PASS, query = 1)
634+
WAVE/Z spikePass = GetLastSetting(numericalValues, sweepNo, key, UNKNOWN_MODE)
635+
ASSERT(WaveExists(spikePass), "Spike pass wave is missing")
636+
637+
if(!spikePass[headstage])
638+
sprintf text, "Sweep %d failed: found spikes", sweepNo
639+
break
640+
endif
641+
endif
642+
break
643+
case PSQ_DA_SCALE:
644+
msg = AD_GetBaselineFailMsg(anaFuncType, numericalValues, sweepNo, headstage)
645+
646+
if(!IsEmpty(msg))
647+
sprintf text, "Sweep %d failed: %s", sweepNo, msg
648+
break
649+
endif
650+
651+
key = CreateAnaFuncLBNKey(anaFuncType, PSQ_FMT_LBN_RB_DASCALE_EXC, query = 1)
652+
WAVE/Z daScaleExc = GetLastSetting(numericalValues, sweepNo, key, UNKNOWN_MODE)
653+
654+
if(WaveExists(daScaleExc) && daScaleExc[headstage])
655+
sprintf text, "Sweep %d failed: Max DA scale exceeded failure", sweepNo
656+
break
657+
endif
658+
659+
key = CreateAnaFuncLBNKey(anaFuncType, PSQ_FMT_LBN_RB_LIMITED_RES, query = 1)
660+
WAVE/Z limitedResolution = GetLastSetting(numericalValues, sweepNo, key, UNKNOWN_MODE)
661+
662+
if(WaveExists(limitedResolution) && limitedResolution[headstage])
663+
sprintf text, "Sweep %d failed: Limited resolution", sweepNo
664+
break
665+
endif
666+
break
667+
case PSQ_RAMP:
668+
msg = AD_GetBaselineFailMsg(anaFuncType, numericalValues, sweepNo, headstage)
669+
670+
if(!IsEmpty(msg))
671+
sprintf text, "Sweep %d failed: %s", sweepNo, msg
672+
break
673+
endif
674+
break
675+
case PSQ_RHEOBASE:
676+
msg = AD_GetBaselineFailMsg(anaFuncType, numericalValues, sweepNo, headstage)
677+
678+
if(!IsEmpty(msg))
679+
sprintf text, "Sweep %d failed: %s", sweepNo, msg
680+
break
681+
endif
682+
683+
// Speciality: Rheobase does not have a Sweep QC entry and only
684+
// baseline QC determines a passing sweep
685+
sprintf text, "Sweep %d passed", sweeps[i]
686+
break
687+
default:
688+
ASSERT(0, "Unsupported analysis function")
689+
endswitch
690+
691+
if(IsEmpty(text))
692+
BUG("Unknown reason for failure")
693+
sprintf text, "Sweep %d failed: Unknown reasons", sweepNo
694+
endif
695+
696+
perSweepFailedMessage += text + "\r"
697+
endfor
698+
699+
if(!ParamIsDefault(numRequiredPasses))
700+
sprintf msg, "Failure as we ran out of sweeps (%d passed but we needed %d).\r%s", numPasses, numRequiredPasses, perSweepFailedMessage
701+
else
702+
sprintf msg, "Failure as we ran out of sweeps.\r%s", perSweepFailedMessage
703+
endif
704+
705+
return RemoveEnding(msg, "\r")
706+
End
707+
620708
/// @brief Show the sweeps of the given `index` entry into the listbox
621709
static Function AD_SelectResult(win, [index])
622710
string win

Packages/MIES/MIES_AnalysisFunctions_PatchSeq.ipf

+1-1
Original file line numberDiff line numberDiff line change
@@ -2924,7 +2924,7 @@ static Function [STRUCT ChirpBoundsInfo s] PSQ_CR_DetermineBoundsState(variable
29242924
return [s]
29252925
End
29262926

2927-
static Function/S PSQ_CR_BoundsActionToString(variable boundsAction)
2927+
Function/S PSQ_CR_BoundsActionToString(variable boundsAction)
29282928

29292929
switch(boundsAction)
29302930
case PSQ_CR_PASS:

0 commit comments

Comments
 (0)