@@ -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)
444427End
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 \r We were not able to find the correct on/off spike pattern (%s)" , prefix , RemoveEnding ( NumericWaveToList ( spikeDetect, ", " , format= "%g" ) , ", " )
484444 return msg
485445End
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"
565517End
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 ""
618570End
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
621709static Function AD_SelectResult ( win, [ index] )
622710 string win
0 commit comments