private static void PathHelper_CalP(List <Route> allPaths, LocalizationGraph localizationGraph, int xind, int yind, int[] temp, double[] temp_costs, double p, int n) { if (xind == 0) { var k = temp_costs.Sum() + localizationGraph.NoLocalCost; //To understand the math, ref to "phosphoRS" papar. var cp = 1 / (1 - MathNet.Numerics.Distributions.Binomial.CDF(p, n, k) + MathNet.Numerics.Distributions.Binomial.PMF(p, n, (int)k)); var route = GetLocalizedPath(localizationGraph, temp); route.Score = k; route.ReversePScore = cp; allPaths.Add(route); return; } foreach (var pre in localizationGraph.array[xind][yind].AllSources) { xind--; yind = pre; temp[xind] = yind; temp_costs[xind] = localizationGraph.array[xind][yind].CurrentCost; PathHelper_CalP(allPaths, localizationGraph, xind, yind, temp, temp_costs, p, n); xind++; } }
//To understand this funciton, ref to "phosphoRS" papar. It is complicated unless you understand how 'phosphoRS' works. //In order to calculate localization probability for each glycosite, one need to get all possible modifications combinations; which is all Routes from a Graph. //The function is to get all routes and calculate the 1/P value for each route which is used to calculate localization probability later. public static List <Route> GetAllPaths_CalP(LocalizationGraph localizationGraph, double p, int n) { List <Route> allPaths = new List <Route>(); int xlength = localizationGraph.array.Length; int ylength = localizationGraph.array.First().Length; //temp is a path. check function GetLocalizedPath. int[] temp = new int[xlength]; double[] temp_cost = new double[xlength]; //A path in graph localization is always the end of the matrix. temp[xlength - 1] = ylength - 1; PathHelper_CalP(allPaths, localizationGraph, xlength - 1, ylength - 1, temp, temp_cost, p, n); return(allPaths); }
//The original path we get is just an array of AdjNode positions. For example, path = [1, 1, 2, 2] means the best nodes are at array[0][1], array[1][1], array[2][2], array[3][2] //This function here is to transfer the path into localized Route. Route contains each glycosite with glycanId. //Basicly, any change from left to right of the path indicates a modification. For example, the path = [1, 1, 2, 2] which means there is a modification at ModPos[0] and ModPos[2] public static Route GetLocalizedPath(LocalizationGraph localizationGraph, int[] path) { Route route = new Route(); if (path.Length == 1) { bool onlyOneLocalized = false; if (localizationGraph.TotalScore > 0) { onlyOneLocalized = true; } route.AddPos(localizationGraph.ModPos[0], localizationGraph.ChildModBoxes[path[0]].ModIds.First(), onlyOneLocalized); return(route); } //Add first mod. If the childBoxes[path[0]].ModIds.Count == 0, means this is an empty childBox. //Otherwise childBoxes[path[0]].ModIds.Count == 1 and childBoxes[path[0]].ModIds only contains one ModId. if (localizationGraph.ChildModBoxes[path[0]].ModIds.Count() != 0) { route.AddPos(localizationGraph.ModPos[0], localizationGraph.ChildModBoxes[path[0]].ModIds.First(), localizationGraph.array[0][path[0]].CurrentCost > 0); } for (int i = 1; i < path.Length; i++) { //If there is a change of the path, get the difference between the two Adjnodes of the array. if (path[i] != path[i - 1]) { var left = GetLeft(localizationGraph.array[i][path[i]].ModBox.ModIds, localizationGraph.array[i - 1][path[i - 1]].ModBox.ModIds).First(); var localPeakExist = localizationGraph.array[i - 1][path[i - 1]].CurrentCost > 0 && (localizationGraph.array[i][path[i]].CurrentCost > 0 || i == path.Length - 1); route.AddPos(localizationGraph.ModPos[i], left, localPeakExist); } } return(route); }
//The modification problem is turned into a Directed Acyclic Graph. The Graph was build with matrix, and dynamic programming is used. //The function goes through the AdjNode[][] array from left to right, assign weight to each AdjNode, keep track of the heaviest previous AdjNode. public static void LocalizeOGlycan(LocalizationGraph localizationGraph, Ms2ScanWithSpecificMass theScan, Tolerance productTolerance, List <Product> products) { var boxSatisfyBox = BoxSatisfyBox(localizationGraph.ChildModBoxes); for (int i = 0; i < localizationGraph.ModPos.Length; i++) { //maxLength: the most mods we can have up to current mod pos; minlengtt: the least mods we can have up to current mod pos. int maxLength = i + 1; int minlength = localizationGraph.ModBox.ModIds.Length - (localizationGraph.ModPos.Length - 1 - i); for (int j = 0; j < localizationGraph.ChildModBoxes.Length; j++) { if (localizationGraph.ChildModBoxes[j].NumberOfMods <= maxLength && localizationGraph.ChildModBoxes[j].NumberOfMods >= minlength) { AdjNode adjNode = new AdjNode(i, j, localizationGraph.ModPos[i], localizationGraph.ChildModBoxes[j]); double cost = 0; if (i != localizationGraph.ModPos.Length - 1) { var fragments = GlycoPeptides.GetLocalFragment(products, localizationGraph.ModPos, i, localizationGraph.ModBox, localizationGraph.ChildModBoxes[j]); cost = CalculateCost(theScan, productTolerance, fragments); } adjNode.CurrentCost = cost; //The first line of the graph didnot have Sources. if (i == 0) { //Get cost adjNode.maxCost = cost; } else { double maxCost = 0; for (int prej = 0; prej <= j; prej++) { //Check if a previous AdjNode exist and the current AdjNode could link to previous AdjNode. if (boxSatisfyBox[j][prej] && localizationGraph.array[i - 1][prej] != null) { adjNode.AllSources.Add(prej); var tempCost = cost + localizationGraph.array[i - 1][prej].maxCost; if (tempCost > maxCost) { adjNode.CummulativeSources.Clear(); adjNode.CummulativeSources.Add(prej); maxCost = tempCost; } else if (tempCost == maxCost) { adjNode.CummulativeSources.Add(prej); } } } adjNode.maxCost = maxCost; } localizationGraph.array[i][j] = adjNode; } } } var unlocalFragments = GlycoPeptides.GetUnlocalFragment(products, localizationGraph.ModPos, localizationGraph.ModBox); var noLocalScore = CalculateCost(theScan, productTolerance, unlocalFragments); localizationGraph.NoLocalCost = noLocalScore; localizationGraph.TotalScore = localizationGraph.array[localizationGraph.ModPos.Length - 1][localizationGraph.ChildModBoxes.Length - 1].maxCost + noLocalScore; }
//Correct Localization Level based on site specific probability. If LocalizationLevel = 1, and there are site probability lower than 0.75, Correct the level to 1b. public static LocalizationLevel CorrectLocalizationLevel(Dictionary <int, List <Tuple <int, double> > > siteSpeciLocalProb, LocalizationGraph localizationGraph, Route route, List <Tuple <int, int, bool> > localizedGlycan, LocalizationLevel localizationLevel) { if (siteSpeciLocalProb == null || localizationLevel != LocalizationLevel.Level1) { return(localizationLevel); } if (localizationGraph.ModPos.Length == 1 && localizationGraph.TotalScore == 0) { return(LocalizationLevel.Level1b); } for (int i = 0; i < localizedGlycan.Count; i++) { var g = localizedGlycan[i]; if (siteSpeciLocalProb[g.Item1].Where(p => p.Item1 == g.Item2).First().Item2 < 0.75) { return(LocalizationLevel.Level1b); } if (!route.Mods[i].Item3) { return(LocalizationLevel.Level1b); } } return(localizationLevel); }