@@ -43,7 +43,9 @@ public class PlotModelStat
4343 "Histogram of Missed Cleavages" ,
4444 "Histogram of Fragment Ion Types by Count" ,
4545 "Histogram of Fragment Ion Types by Intensity" ,
46- "Histogram of Ids by Retention Time"
46+ "Histogram of Ids by Retention Time" ,
47+ "Histogram of Spectral Match Ambiguity Levels" ,
48+ "Histogram of Notch (Ambiguous PSMs Split Across Notches)"
4749 } ;
4850
4951 public PlotModel Model => privateModel ;
@@ -124,6 +126,12 @@ private void createPlot(string plotType)
124126 case "Histogram of Ids by Retention Time" :
125127 histogramPlot ( 12 ) ;
126128 break ;
129+ case "Histogram of Spectral Match Ambiguity Levels" :
130+ histogramPlot ( 13 ) ;
131+ break ;
132+ case "Histogram of Notch (Ambiguous PSMs Split Across Notches)" :
133+ histogramPlot ( 14 ) ;
134+ break ;
127135 }
128136 }
129137
@@ -153,7 +161,7 @@ private void histogramPlot(int plotType)
153161 int [ ] totalCounts ;
154162 int categoriesPerGroup = 0 ;
155163 List < string > allGroupKeys = null ;
156- bool isCategoryHistogram = plotType == 5 || plotType == 10 || plotType == 11 ;
164+ bool isCategoryHistogram = plotType == 5 || plotType == 10 || plotType == 11 || plotType == 13 ;
157165
158166 if ( isCategoryHistogram )
159167 {
@@ -336,6 +344,34 @@ private HistogramRawData GetHistogramData(int plotType)
336344 dictsBySourceFile . Add ( fileName , result ) ;
337345 }
338346 break ;
347+ case 13 : // Histogram of Spectral Match Ambiguity Levels
348+ xAxisTitle = "Ambiguity Level" ;
349+ labelAngle = 0 ;
350+ foreach ( var fileName in psmsBySourceFile . Keys )
351+ {
352+ var result = psmsBySourceFile [ fileName ]
353+ . GroupBy ( p => NormalizeAmbiguityLevel ( p . AmbiguityLevel ) )
354+ . ToDictionary ( p => p . Key , p => p . Count ( ) ) ;
355+ dictsBySourceFile . Add ( fileName , result ) ;
356+ }
357+ break ;
358+ case 14 : // Histogram of Notch (ambiguous PSMs contribute to each of their pipe-delimited notches)
359+ xAxisTitle = "Notch" ;
360+ binSize = 1 ;
361+ labelAngle = 0 ;
362+ foreach ( var fileName in psmsBySourceFile . Keys )
363+ {
364+ var values = new List < double > ( ) ;
365+ foreach ( var psm in psmsBySourceFile [ fileName ] )
366+ {
367+ foreach ( double notch in ParseAmbiguousNotchValues ( psm . Notch ) )
368+ values . Add ( notch ) ;
369+ }
370+ numbersBySourceFile . Add ( fileName , values ) ;
371+ var results = values . GroupBy ( p => roundToBin ( p , binSize ) ) . OrderBy ( p => p . Key ) . Select ( p => p ) ;
372+ dictsBySourceFile . Add ( fileName , results . ToDictionary ( p => p . Key . ToString ( CultureInfo . InvariantCulture ) , v => v . Count ( ) ) ) ;
373+ }
374+ break ;
339375 }
340376
341377 return new HistogramRawData ( xAxisTitle , yAxisTitle , binSize , labelAngle , numbersBySourceFile , dictsBySourceFile ) ;
@@ -515,6 +551,13 @@ private Dictionary<string, int> GetCategoryDictForGroup(int plotType, Observable
515551 return mods . GroupBy ( p => p . IdWithMotif ) . ToDictionary ( p => p . Key , v => v . Count ( ) ) ;
516552 }
517553
554+ if ( plotType == 13 )
555+ {
556+ return groupPsms
557+ . GroupBy ( p => NormalizeAmbiguityLevel ( p . AmbiguityLevel ) )
558+ . ToDictionary ( p => p . Key , p => p . Count ( ) ) ;
559+ }
560+
518561 var allMatchedIons = groupPsms . SelectMany ( p => p . MatchedIons ) . ToList ( ) ;
519562 if ( plotType == 10 )
520563 {
@@ -1013,6 +1056,7 @@ private IEnumerable<double> GetNumbersFromPsms(ObservableCollection<SpectrumMatc
10131056 8 => GetHydrophobicityScores ( psms ) ,
10141057 9 => psms . Where ( p => ! p . MissedCleavage . Contains ( "|" ) ) . Select ( p => double . Parse ( p . MissedCleavage ) ) ,
10151058 12 => psms . Select ( p => ( double ) ( int ) Math . Round ( p . RetentionTime , 0 ) ) ,
1059+ 14 => psms . SelectMany ( p => ParseAmbiguousNotchValues ( p . Notch ) ) ,
10161060 _ => Enumerable . Empty < double > ( )
10171061 } ;
10181062 }
@@ -1042,6 +1086,37 @@ public HistItem(double value, int categoryIndex, string bin, int total, string g
10421086 }
10431087 }
10441088
1089+ private static IEnumerable < string > SplitAmbiguousNotch ( string notch )
1090+ {
1091+ if ( string . IsNullOrWhiteSpace ( notch ) )
1092+ return new [ ] { "0" } ;
1093+
1094+ return notch . Split ( '|' )
1095+ . Select ( p => p . Trim ( ) )
1096+ . Where ( p => p . Length > 0 )
1097+ . DefaultIfEmpty ( "0" ) ;
1098+ }
1099+
1100+ private static IEnumerable < double > ParseAmbiguousNotchValues ( string notch )
1101+ {
1102+ foreach ( var part in SplitAmbiguousNotch ( notch ) )
1103+ {
1104+ if ( double . TryParse ( part , NumberStyles . Float , CultureInfo . InvariantCulture , out double value ) )
1105+ yield return value ;
1106+ else
1107+ yield return 0.0 ;
1108+ }
1109+ }
1110+
1111+ private static string NormalizeAmbiguityLevel ( string ambiguityLevel )
1112+ {
1113+ if ( string . IsNullOrWhiteSpace ( ambiguityLevel ) )
1114+ return "1" ;
1115+
1116+ var first = ambiguityLevel . Split ( '|' ) [ 0 ] . Trim ( ) ;
1117+ return string . IsNullOrEmpty ( first ) ? "1" : first ;
1118+ }
1119+
10451120 /// <summary>
10461121 /// Orders strings numerically if all values are numeric, otherwise alphabetically.
10471122 /// </summary>
0 commit comments