package com.compomics.util.experiment.identification.ptm; import com.compomics.util.Util; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; /** * This class contains convenience methods to map ptms on potential sites. * * @author Marc Vaudel */ public class PtmSiteMapping { /** * Aligns two series of integer, minimizing the distance between them and * excluding outliers. * * Example: series1 = {0, 1, 13, 25, 15, 6, 99} series2 = {100, 2, 12, 14, * 18, 30, 115, 1000} result = {0>null, 1>2, 6>null, 13>12, * 15>14, 25>18, 99>100} * * @param serie1 first list of integer * @param serie2 second list of integer * @return a map of the doublets created. */ public static HashMap<Integer, Integer> align(Collection<Integer> serie1, Collection<Integer> serie2) { HashMap<Integer, Integer> result = new HashMap<Integer, Integer>(); if (serie1 == null || serie1.isEmpty()) { return result; } ArrayList<Integer> sortedSerie1 = new ArrayList<Integer>(serie1); Collections.sort(sortedSerie1); if (serie2 == null || serie2.isEmpty()) { for (int index : serie1) { result.put(index, null); } return result; } ArrayList<Integer> sortedSerie2 = new ArrayList<Integer>(serie2); Collections.sort(sortedSerie2); int lastj = 0; int firsti = 0; for (int i = 0; i < sortedSerie1.size() - 1; i++) { if (Math.abs(sortedSerie1.get(i + 1) - sortedSerie2.get(0)) < Math.abs(sortedSerie1.get(i) - sortedSerie2.get(0))) { result.put(sortedSerie1.get(i), null); firsti = i + 1; } else { break; } } for (int i = firsti; i < sortedSerie1.size(); i++) { Integer bestj = null; Integer bestDistance = null; if (lastj < sortedSerie2.size()) { for (int j = lastj; j < sortedSerie2.size(); j++) { if (i < sortedSerie1.size() - 1 && (sortedSerie2.get(j) >= sortedSerie1.get(i + 1) || Math.abs(sortedSerie2.get(j) - sortedSerie1.get(i + 1)) < Math.abs(sortedSerie2.get(j) - sortedSerie1.get(i)))) { break; } if (bestDistance == null || Math.abs(sortedSerie2.get(j) - sortedSerie1.get(i)) < bestDistance) { bestDistance = Math.abs(sortedSerie2.get(j) - sortedSerie1.get(i)); bestj = j; } } } if (bestj != null) { result.put(sortedSerie1.get(i), sortedSerie2.get(bestj)); lastj = bestj + 1; } else { result.put(sortedSerie1.get(i), null); } } return result; } /** * Aligns two series of integer, minimizing the distance between them. * * Example: serie1 = {0, 1, 13, 25, 15, 6, 99} serie2 = {100, 2, 12, 14, 18, * 30, 115, 1000} result = {0> 115, 1>2, 6>30, 13>12, 15>14, * 25>18, 99>100} * * @param serie1 first list of integer * @param serie2 second list of integer * @return a map of the doublets created. */ public static HashMap<Integer, Integer> alignAll(Collection<Integer> serie1, Collection<Integer> serie2) { HashMap<Integer, Integer> tempResult, result = new HashMap<Integer, Integer>(); if (serie1 == null || serie1.isEmpty()) { return result; } if (serie2 == null || serie2.isEmpty()) { for (int index : serie1) { result.put(index, null); } return result; } int diff = Math.max(serie1.size() - serie2.size(), 0); int nNull = diff + 1; while (nNull > diff) { ArrayList<Integer> tempSerie1 = new ArrayList<Integer>(); ArrayList<Integer> tempSerie2 = new ArrayList<Integer>(serie2); Integer i2; for (int i1 : serie1) { i2 = result.get(i1); if (i2 != null) { tempSerie2.remove(i2); } else { tempSerie1.add(i1); } } tempResult = align(tempSerie1, tempSerie2); nNull = 0; for (int i1 : tempResult.keySet()) { i2 = tempResult.get(i1); if (i2 == null) { nNull++; } result.put(i1, i2); } } return result; } /** * Aligns a series of integer on possible targets maximizing the number of * matched targets. * * Example: * * input = { 0 > {100, 2, 12, 14, 18, 30, 115, 1000}, 1 > {12}, 2 > * {3, 12, 14}, 8 > {12}, 13 > {3, 12, 14}, 25 > {100, 2, 12, 14, * 18, 30, 115, 1000}, 15 > {100, 2, 12, 14, 18, 30, 115, 1000}, 6 > * {100, 2, 12, 14, 18, 30, 115, 1000}, 99 > {3} } * * result = {1 > null, 8 > 12, 99 > 3, 13 > 14, 2 > null, 0 * > 2, 6 > 100, 15 > 18, 25 > 30} * * @param input the input map * @return a map of the doublets created. */ public static HashMap<Integer, Integer> alignAll(HashMap<Integer, ArrayList<Integer>> input) { HashMap<Integer, Integer> tempResult, result = new HashMap<Integer, Integer>(); if (input == null || input.isEmpty()) { return result; } HashMap<Integer, ArrayList<Integer>> inputCopy = new HashMap<Integer, ArrayList<Integer>>(); for (int i1 : input.keySet()) { inputCopy.put(i1, new ArrayList<Integer>()); for (int i2 : input.get(i1)) { inputCopy.get(i1).add(i2); } } while (!inputCopy.isEmpty()) { HashMap<Integer, ArrayList<Integer>> sizesMap = new HashMap<Integer, ArrayList<Integer>>(); for (int i : inputCopy.keySet()) { if (inputCopy.get(i) != null && !inputCopy.get(i).isEmpty()) { int size = inputCopy.get(i).size(); if (!sizesMap.containsKey(size)) { sizesMap.put(size, new ArrayList<Integer>()); } sizesMap.get(size).add(i); } else { inputCopy.remove(i); } } ArrayList<Integer> sizes = new ArrayList<Integer>(sizesMap.keySet()); Collections.sort(sizes); int size = sizes.get(0); ArrayList<Integer> serie1 = new ArrayList<Integer>(); int i1temp = sizesMap.get(size).get(0); ArrayList<Integer> serie2 = inputCopy.get(i1temp); for (int i1 : sizesMap.get(size)) { if (Util.sameLists(serie2, inputCopy.get(i1))) { serie1.add(i1); } } tempResult = alignAll(serie1, serie2); result.putAll(tempResult); for (int i1 : inputCopy.keySet()) { ArrayList<Integer> toRemove2 = new ArrayList<Integer>(); for (int i2 : inputCopy.get(i1)) { if (tempResult.containsValue(i2)) { toRemove2.add(i2); } } for (Integer i2 : toRemove2) { inputCopy.get(i1).remove(i2); } } for (Integer i1 : serie1) { inputCopy.remove(i1); sizesMap.get(size).remove(i1); } ArrayList<Integer> toRemove1 = new ArrayList<Integer>(); for (int i1 : inputCopy.keySet()) { if (inputCopy.get(i1).isEmpty()) { toRemove1.add(i1); result.put(i1, null); } } for (int i1 : toRemove1) { inputCopy.remove(i1); } if (sizesMap.get(size).isEmpty()) { sizesMap.remove(size); } } return result; } }