/** * Copyright Copyright 2010-14 Simon Andrews * * This file is part of BamQC. * * BamQC is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * BamQC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with BamQC; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Changelog: * - Simon Andrews: Class creation. */ package uk.ac.babraham.BamQC.Graphs; import java.util.Vector; import uk.ac.babraham.BamQC.BamQCConfig; /** * The base group class is a simple way to create a set of bins into * which positions within a read can be put such that early positions * get a group to themselves and later positions get averaged so that * general trends can still be observed. * @author Simon Andrews */ public class BaseGroup { private int lowerCount; private int upperCount; public static BaseGroup [] makeBaseGroups (int maxLength) { if (BamQCConfig.getInstance().nogroup) { return(makeUngroupedGroups(maxLength)); } else if (BamQCConfig.getInstance().expgroup) { return(makeExponentialBaseGroups(maxLength)); } else { return(makeLinearBaseGroups(maxLength)); } } public static BaseGroup [] makeUngroupedGroups (int maxLength) { int startingBase = 1; int interval = 1; Vector<BaseGroup> groups = new Vector<BaseGroup>(); while (startingBase <= maxLength) { int endBase = startingBase+(interval-1); if (endBase > maxLength) endBase = maxLength; BaseGroup bg = new BaseGroup(startingBase, endBase); groups.add(bg); startingBase += interval; } return groups.toArray(new BaseGroup[0]); } public static BaseGroup [] makeExponentialBaseGroups (int maxLength) { int startingBase = 1; int interval = 1; Vector<BaseGroup> groups = new Vector<BaseGroup>(); while (startingBase <= maxLength) { int endBase = startingBase+(interval-1); if (endBase > maxLength) endBase = maxLength; BaseGroup bg = new BaseGroup(startingBase, endBase); groups.add(bg); startingBase += interval; // See if we need to increase the interval if (startingBase == 10 && maxLength > 75) { interval = 5; } if (startingBase == 50 && maxLength > 200) { interval = 10; } if (startingBase == 100 && maxLength > 300) { interval = 50; } if (startingBase == 500 && maxLength > 1000) { interval = 100; } if (startingBase == 1000 && maxLength > 2000) { interval = 500; } } return groups.toArray(new BaseGroup[0]); } private static int getLinearInterval (int length) { // The the first 9bp as individual residues since odd stuff // can happen there, then we find a grouping value which gives // us a total set of groups below 75. We limit the intervals // we try to sensible whole numbers. int [] baseValues = new int [] {2,5,10}; int multiplier = 1; while (true) { for (int b=0;b<baseValues.length;b++) { int interval = baseValues[b] * multiplier; int groupCount = 9 + ((length-9)/interval); if ((length-9) % interval != 0) { groupCount += 1; } if (groupCount < 75) return interval; } multiplier *= 10; if (multiplier == 10000000) { throw new IllegalStateException("Couldn't find a sensible interval grouping for length '"+length+"'"); } } } public static BaseGroup [] makeLinearBaseGroups (int maxLength) { // For lengths below 75bp we just return everything. if (maxLength <= 75) return makeUngroupedGroups(maxLength); // We need to work out what interval we're going to use. int interval = getLinearInterval(maxLength); int startingBase = 1; Vector<BaseGroup> groups = new Vector<BaseGroup>(); while (startingBase <= maxLength) { int endBase = startingBase+(interval-1); if (startingBase < 10) endBase = startingBase; if (startingBase == 10 && interval > 10) { endBase = interval-1; } if (endBase > maxLength) endBase = maxLength; BaseGroup bg = new BaseGroup(startingBase, endBase); groups.add(bg); if (startingBase < 10) { startingBase +=1; } else if (startingBase == 10 && interval > 10) { startingBase = interval; } else { startingBase += interval; } } return groups.toArray(new BaseGroup[0]); } /** * * @param lowerCount * @param upperCount */ private BaseGroup (int lowerCount, int upperCount) { this.lowerCount = lowerCount; this.upperCount = upperCount; } public int lowerCount () { return lowerCount; } public int upperCount () { return upperCount; } public boolean containsValue (int value) { return value>=lowerCount && value<=upperCount; } @Override public String toString () { if (lowerCount == upperCount) { return ""+lowerCount; } return ""+lowerCount+"-"+upperCount; } }