Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 29 additions & 18 deletions mzLib/FlashLFQ/FlashLFQResults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
public readonly Dictionary<string, ProteinGroup> ProteinGroups;
public readonly Dictionary<SpectraFileInfo, List<ChromatographicPeak>> Peaks;
private readonly HashSet<string> _peptideModifiedSequencesToQuantify;
public IDictionary<string, Dictionary<PeakRegion, List<ChromatographicPeak>>> IsobaricPeptideDict = null;
public IDictionary<PeptideMassBin, Dictionary<PeakRegion, List<ChromatographicPeak>>> IsobaricPeptideDict = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be PeptideMzBin unless it is deconvoluted neutral mass. In that case, Mass is fine.

public string PepResultString { get; set; }
public double MbrQValueThreshold { get; set; }

Expand Down Expand Up @@ -796,13 +796,10 @@
{
int isoGroupIndex = 1;
//If the isobaric peptide dictionary is not empty, then we need to revise the peptide list.
foreach (var isoPeptides in IsobaricPeptideDict.Where(p=>p.Value.Count != 0))
foreach (var isoPeptide in IsobaricPeptideDict.Where(p=>p.Value.Count != 0))
{
string peptideSequence = isoPeptides.Key;
Peptide originalPeptide = PeptideModifiedSequences[peptideSequence];

// Remove the formal peptide from the peptide list
var allIDs = isoPeptides.Value.Values
var allIDs = isoPeptide.Value.Values
.SelectMany(p => p)
.Where(p => p != null)
.SelectMany(p=>p.Identifications)
Expand All @@ -820,32 +817,46 @@
// Add the isobaric peptides to the peptide list

//If there is only one peak for the isobaric peptides, then we don't view them as isobaric peptides.
if (isoPeptides.Value.Values.Count == 1)
{
var isoPeptidePeaks = isoPeptides.Value.Values.First();
var allSeq = isoPeptidePeaks
.Where(p => p != null)
.SelectMany(p => p.Identifications)
.Select(p => p.ModifiedSequence)
.Distinct()
.ToList();
Peptide peptide = new Peptide(string.Join(" | ", allSeq), originalPeptide.BaseSequence, originalPeptide.UseForProteinQuant, originalPeptide.ProteinGroups);
if (isoPeptide.Value.Values.Count == 1)
{
var ModSeq = isoPeptide.Key.Ids.Select(p=>p.ModifiedSequence).ToList();
var baseSeq = isoPeptide.Key.Ids.Select(p => p.BaseSequence).ToList();
var useForQ = isoPeptide.Key.Ids.All(p => p.UseForProteinQuant);
var pg = isoPeptide.Key.Ids.SelectMany(p => p.ProteinGroups).ToHashSet();
var isoPeptidePeaks = isoPeptide.Value.Values.First();
Peptide peptide = new Peptide(string.Join(" | ", ModSeq), string.Join("|", baseSeq), useForQ, pg);

Check warning on line 827 in mzLib/FlashLFQ/FlashLFQResults.cs

View check run for this annotation

Codecov / codecov/patch

mzLib/FlashLFQ/FlashLFQResults.cs#L821-L827

Added lines #L821 - L827 were not covered by tests
peptide.SetIsobaricPeptide(isoPeptidePeaks); //When we set the peptide as IsobaricPeptide, then the retention time, intensity and detectionType will be set from the chromPeak automatically.
PeptideModifiedSequences[peptide.Sequence] = peptide;
}

//If there are multiple peaks for the isobaric peptides, then we view them as isobaric peptides.
else
{
int peakIndex = 1;
foreach (var isoPeptidePeaks in isoPeptides.Value.Values.ToList())
foreach (var isoPeptidePeaks in isoPeptide.Value.Values.ToList())
{
var allSeq = isoPeptidePeaks
.Where(p => p != null)
.SelectMany(p => p.Identifications)
.Select(p => p.ModifiedSequence)
.Distinct()
.ToList();
Peptide peptide = new Peptide(string.Join(" | ", allSeq) + " Isopeptide_peak" + peakIndex, originalPeptide.BaseSequence, originalPeptide.UseForProteinQuant, originalPeptide.ProteinGroups, isoGroupIndex, peakIndex);
var allBaseSeq = isoPeptidePeaks.Where(p => p != null)
.SelectMany(p => p.Identifications)
.Select(p => p.BaseSequence)
.Distinct()
.ToList();
var allUseForQ = isoPeptidePeaks
.Where(p => p != null)
.SelectMany(p => p.Identifications)
.All(p => p.UseForProteinQuant);
var allProteinGroups = isoPeptidePeaks
.Where(p => p != null)
.SelectMany(p => p.Identifications)
.SelectMany(p => p.ProteinGroups)
.Distinct()
.ToHashSet();
Peptide peptide = new Peptide(string.Join(" | ", allSeq) + " Isopeptide_peak" + peakIndex, string.Join("|", allBaseSeq), allUseForQ, allProteinGroups, isoGroupIndex, peakIndex);
peptide.SetIsobaricPeptide(isoPeptidePeaks); //When we set the peptide as IsobaricPeptide, then the retention time, intensity and detectionType will be set from the chromPeak automatically.
PeptideModifiedSequences[peptide.Sequence] = peptide;
peakIndex++;
Expand Down
58 changes: 44 additions & 14 deletions mzLib/FlashLFQ/FlashLfqEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using FlashLFQ.Interfaces;

[assembly: InternalsVisibleTo("TestFlashLFQ")]
[assembly: InternalsVisibleTo("Test")]

namespace FlashLFQ
{
Expand Down Expand Up @@ -47,7 +48,7 @@ public class FlashLfqEngine
//IsoTracker settings
public readonly bool IsoTracker; //Searching parameter for the FlashLFQ engine
public bool IsoTrackerIsRunning { get; private set;} // a flag used to indicate if the isobaric case is running, used to control the indexEngine
public ConcurrentDictionary<string, Dictionary<PeakRegion, List<ChromatographicPeak>>> IsobaricPeptideDict { get; private set; } // The dictionary of isobaric peaks for each modified sequence
public ConcurrentDictionary<PeptideMassBin, Dictionary<PeakRegion, List<ChromatographicPeak>>> IsobaricPeptideDict { get; private set; } // The dictionary of isobaric peaks for each modified sequence

// MBR settings
public readonly bool MatchBetweenRuns;
Expand Down Expand Up @@ -253,7 +254,7 @@ public FlashLfqResults Run()
if (IsoTracker)
{
IsoTrackerIsRunning = true; // Turn on the flag, then we will use the separate indexEngine for each files
IsobaricPeptideDict = new ConcurrentDictionary<string, Dictionary<PeakRegion, List<ChromatographicPeak>>>();
IsobaricPeptideDict = new ConcurrentDictionary<PeptideMassBin, Dictionary<PeakRegion, List<ChromatographicPeak>>>();
QuantifyIsobaricPeaks();
_results.IsobaricPeptideDict = IsobaricPeptideDict;
AddIsoPeaks();
Expand Down Expand Up @@ -1967,21 +1968,18 @@ private void QuantifyIsobaricPeaks()
double lastReportedProgress = 0;
double currentProgress = 0;

var idGroupedBySeq = _allIdentifications
.Where(p => p.BaseSequence != p.ModifiedSequence && !p.IsDecoy)
.GroupBy(p => new
{ p.BaseSequence, MonoisotopicMassGroup = Math.Round(p.MonoisotopicMass / 0.0001) })
.ToList();

Parallel.ForEach(Partitioner.Create(0, idGroupedBySeq.Count),
// Group the identifications by their mass, and build the isobaricPeptide
Tolerance massTolerance = new PpmTolerance(PpmTolerance);
List<PeptideMassBin> peptideMassBins = SortIsobaricPeptide(_allIdentifications, massTolerance);
Parallel.ForEach(Partitioner.Create(0, peptideMassBins.Count),
new ParallelOptions { MaxDegreeOfParallelism = MaxThreads },
(range, loopState) =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
var idGroup = idGroupedBySeq[i];
var isobaricPeptide = peptideMassBins[i];
List<XIC> xicGroup = new List<XIC>();
var mostCommonChargeIdGroup = idGroup.GroupBy(p => p.PrecursorChargeState).OrderBy(p => p.Count()).Last();
var mostCommonChargeIdGroup = isobaricPeptide.Ids.GroupBy(p => p.PrecursorChargeState).OrderBy(p => p.Count()).Last();
var id = mostCommonChargeIdGroup.First();

// Try to get the primitive window for the XIC , from the (firstOne - 2) -> (lastOne + 2)
Expand Down Expand Up @@ -2010,7 +2008,7 @@ private void QuantifyIsobaricPeaks()
if (xicGroup.Count > 1)
{
// Step 1: Find the XIC with most IDs then, set as reference XIC
xicGroup.OrderBy(p => p.Ids.Count()).First().Reference = true;
xicGroup.OrderByDescending(p => p.Ids.Count()).First().Reference = true;

//Step 2: Build the XICGroups
XICGroups xICGroups = new XICGroups(xicGroup);
Expand Down Expand Up @@ -2038,15 +2036,15 @@ private void QuantifyIsobaricPeaks()
}
}
}
IsobaricPeptideDict.TryAdd(id.ModifiedSequence, sharedPeaksDict);
IsobaricPeptideDict.TryAdd(isobaricPeptide, sharedPeaksDict);
}

// report search progress (proteins searched so far out of total proteins in database)
if (!Silent)
{
Interlocked.Increment(ref isoGroupsSearched);

double percentProgress = ((double)isoGroupsSearched / idGroupedBySeq.Count * 100);
double percentProgress = ((double)isoGroupsSearched / peptideMassBins.Count * 100);
currentProgress = Math.Max(percentProgress, currentProgress);

if (currentProgress > lastReportedProgress + 10)
Expand All @@ -2061,6 +2059,38 @@ private void QuantifyIsobaricPeaks()
Console.WriteLine("Finished quantifying isobaric species!");
}

/// <summary>
/// Sort ids in the IDList and classify into isobaricPeptide by their mass.
/// </summary>
internal List<PeptideMassBin> SortIsobaricPeptide(List<Identification> _allIdentifications, Tolerance massTolerance)
{
List<PeptideMassBin> isobaricPeptides = new List<PeptideMassBin>();
var ids = _allIdentifications.Where(p => p.BaseSequence != p.ModifiedSequence).OrderBy(p => p.PeakfindingMass).ToList();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a comment explaining this restriction


for (int i = 0; i < ids.Count; i++)
{
Identification id = ids[i];
PeptideMassBin isobaricPeptide = new PeptideMassBin(id, massTolerance);

for (int j = i+1; j < ids.Count; j++)
{
Identification id2 = ids[j];
if (id2.PeakfindingMass < isobaricPeptide.MaxMass)
{
isobaricPeptide.Ids.Add(id2);
i = j;
}
else
{
i = j-1;
break;
}
}
isobaricPeptides.Add(isobaricPeptide);
}
return isobaricPeptides;
}

/// <summary>
/// Build the XIC from the given IDs.
/// </summary>
Expand Down
30 changes: 30 additions & 0 deletions mzLib/FlashLFQ/IsoTracker/PeptideMassBin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using MzLibUtil;
using System.Collections.Generic;


namespace FlashLFQ.IsoTracker
{
/// <summary>
/// This class is used to group isobaric peptides together based on their mass.
/// </summary>
public class PeptideMassBin
{
public double MaxMass { get; private set; } // The mass of the isobaric peptide
public List<Identification> Ids { get; set; } // The identification of the isobaric peptide

public PeptideMassBin(Identification id, Tolerance tolerance)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think you should specify the kind of tolerance (ppm or mass)

{
Ids = new List<Identification>() { id };
MaxMass = tolerance.GetMaximumValue(id.PeakfindingMass);
}

public override bool Equals(object obj)
{
return base.Equals(obj);
}

Check warning on line 24 in mzLib/FlashLFQ/IsoTracker/PeptideMassBin.cs

View check run for this annotation

Codecov / codecov/patch

mzLib/FlashLFQ/IsoTracker/PeptideMassBin.cs#L22-L24

Added lines #L22 - L24 were not covered by tests
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
9 changes: 6 additions & 3 deletions mzLib/Test/Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -603,16 +603,19 @@
<None Update="XICData\AllPSMs.psmtsv">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="XICData\AllPSMs_IsoID.psmtsv">
<None Update="XICData\AllPSMs_MassTolerance.psmtsv">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="XICData\AllPSMs_IsobaricPeptide.psmtsv">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="XICData\AllPSMs_IsoID_Combined.psmtsv">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="XICData\AllPSMs_IsoID_Mixture.psmtsv">
<None Update="XICData\AllPSMs_Ambiguity.psmtsv">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="XICData\AllPSMs_IsoID_MonoIsotopicmassTolerance.psmtsv">
<None Update="XICData\IDList_5000Ids.psmtsv">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="DataFiles\centroid_1x_MS1_4x_autoMS2.d\**">
Expand Down
Loading
Loading