/* * Eoulsan development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public License version 2.1 or * later and CeCILL-C. This should be distributed with the code. * If you do not have a copy, see: * * http://www.gnu.org/licenses/lgpl-2.1.txt * http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.txt * * Copyright for this code is held jointly by the Genomic platform * of the Institut de Biologie de l'École normale supérieure and * the individual authors. These should be listed in @author doc * comments. * * For more information on the Eoulsan project and its aims, * or to join the Eoulsan Google group, visit the home page * at: * * http://outils.genomique.biologie.ens.fr/eoulsan * */ package fr.ens.biologie.genomique.eoulsan.modules.expression; import java.util.HashMap; import java.util.Map; /** * This class handle exon coverage. * @since 1.0 * @author Laurent Jourdren */ public class ExonsCoverage { private final Map<String, ExonCoverage> exons = new HashMap<>(); private int alignmentCount; private final static class ExonCoverage { private final int exonStart; private final int exonEnd; private final byte[] coverage; /** * Add an alignment * @param alignmentStart start of the alignment * @param alignmentEnd end of the alignment */ public void addAlignment(final int alignmentStart, final int alignmentEnd) { if (alignmentStart < 1) { throw new IllegalArgumentException( "Start position can't be lower than 1."); } if (alignmentEnd < alignmentStart) { throw new IllegalArgumentException( "End position can't be lower than start position."); } // Test if alignment is outside the exon if (alignmentStart > this.exonEnd | alignmentEnd < this.exonStart) { return; } final int start = alignmentStart < this.exonStart ? this.exonStart : alignmentStart; final int end = alignmentEnd > this.exonEnd ? this.exonEnd : alignmentEnd; for (int i = start; i <= end; i++) { this.coverage[i - this.exonStart] = 1; } } /** * Get the number of base covered. * @return the number of base not covered */ public int getCovered() { int count = 0; final int len = this.coverage.length; for (int i = 0; i < len; i++) { if (this.coverage[i] > 0) { count++; } } return count; } /** * Get start position. * @return The start position */ public int getStart() { return this.exonStart; } /** * Get the stop position. * @return The end position */ public int getEnd() { return this.exonEnd; } // // Constructor // /** * Public constructor. * @param start start of the exon * @param end end of the exon */ public ExonCoverage(final int start, final int end) { if (start < 1) { throw new IllegalArgumentException( "Start position can't be lower than 1."); } if (end < start) { throw new IllegalArgumentException( "End position can't be lower than start position."); } this.exonStart = start; this.exonEnd = end; this.coverage = new byte[end - start + 1]; } } /** * Add alignment to the gene coverage * @param exonStart start of the exon * @param exonEnd end of the exon * @param alignmentStart start of the alignment * @param alignmentEnd end of the alignment * @param incrementAlignmentCount true if the alignment count must be * incremented */ public void addAlignment(final int exonStart, final int exonEnd, final int alignmentStart, final int alignmentEnd, final boolean incrementAlignmentCount) { final String key = exonStart + "_" + exonEnd; final ExonCoverage exon; if (this.exons.containsKey(key)) { exon = this.exons.get(key); } else { exon = new ExonCoverage(exonStart, exonEnd); this.exons.put(key, exon); } exon.addAlignment(alignmentStart, alignmentEnd); if (incrementAlignmentCount) { this.alignmentCount++; } } public int getAlignmentCount() { return this.alignmentCount; } public int getExonCount() { return this.exons.size(); } public int getCovered() { int count = 0; for (Map.Entry<String, ExonCoverage> e : this.exons.entrySet()) { count += e.getValue().getCovered(); } return count; } public int getNotCovered(final int geneLength) { return geneLength - getCovered(); } public int getLength() { int count = 0; for (Map.Entry<String, ExonCoverage> e : this.exons.entrySet()) { ExonCoverage ge = e.getValue(); count += ge.exonEnd - ge.exonStart + 1; } return count; } /** * Clear data; */ public void clear() { this.exons.clear(); this.alignmentCount = 0; } }