/* * The MIT License (MIT) * * Copyright (c) 2007-2015 Broad Institute * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.broad.igv.feature; //~--- non-JDK imports -------------------------------------------------------- import org.apache.log4j.Logger; import org.broad.igv.ui.IGV; import org.broad.igv.util.collections.MultiMap; import htsjdk.tribble.Feature; import java.awt.*; import java.util.List; /** * @author jrobinso */ abstract public class AbstractFeature implements IGVFeature, htsjdk.tribble.Feature { private static Logger log = Logger.getLogger(AbstractFeature.class); protected Strand strand = Strand.NONE; protected String chromosome; protected int start = -1; protected int end = -1; protected String type = ""; protected Color color; protected String description; protected MultiMap<String, String> attributes; protected String name = ""; /** * The 0-based reading frame offset from start position. * Only well defined for Exon-type features */ protected int readingFrame = -1; public AbstractFeature() { } /** * @param chr * @param start * @param end * @param strand */ public AbstractFeature(String chr, int start, int end, Strand strand) { this.chromosome = chr; this.start = start; this.end = end; this.strand = strand; } public String getIdentifier() { return null; } public void setType(String type) { this.type = type; } public String getType() { return type; } public String getName() { return name; } public List<Exon> getExons() { return null; } public boolean hasExons() { return false; } public float getScore() { return Float.NaN; } public String getChr() { return chromosome; } public String getContig() { return chromosome; } /** * By default features are 1 bp wide * * @return */ public int getEnd() { return end; } public int getLength() { return end - start; } public int getStart() { return start; } /** * Return true if the feature is completely contained within the bounds of this * feature. amd is on the same strand.. * <p/> * * @param feature * @return */ public boolean contains(IGVFeature feature) { if (feature == null) { return false; } if (!this.getChr().equals(feature.getChr()) || this.getStrand() != feature.getStrand()) { return false; } if ((feature.getStart() >= this.getStart()) && (feature.getEnd() <= this.getEnd())) { return true; } else { return false; } } public void setEnd(int end) { this.end = end; } public void setStart(int start) { this.start = start; } public Strand getStrand() { return strand; } public void setStrand(Strand strand) { this.strand = strand; } public boolean hasStrand() { return ((strand != null) && (strand != Strand.NONE)); } public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } public void setColor(String[] rgb, int nTokens) { try { if (nTokens < 3) { if (rgb[0].equals(".")) { return; } color = new Color(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[0]), Integer.parseInt(rgb[0])); } else { color = new Color(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2])); } } catch (NumberFormatException numberFormatException) { } } public void setDescription(String description) { this.description = description; } public String getDescription() { return (description == null) ? getName() : description; } public MultiMap<String, String> getAttributes() { return attributes; } public void setAttributes(MultiMap<String, String> attributes) { this.attributes = attributes; } public void setAttribute(String key, String value) { if(attributes == null) { attributes = new MultiMap<String, String>(); } attributes.put(key, value); } public boolean contains(double location) { return location >= getStart() && location < getEnd(); } public boolean overlaps(Feature anotherFeature) { return end >= anotherFeature.getStart() && start <= anotherFeature.getEnd() && chromosome.equals(anotherFeature.getChr()); } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @param chromosome the chromosome to set */ public void setChr(String chromosome) { this.chromosome = chromosome; } /** * Get human readable locus string. * It is assumed that this.start and this.end are 0-based * and end-exclusive, and the returned string is 1-based * and end-inclusive. So basically we just add 1 to the start. * * @return */ public String getLocusString() { return getChr() + ":" + (getStart() + 1) + "-" + getEnd(); } protected String getAttributeString() { StringBuffer buf = new StringBuffer(); // 30 attributes is the maximum visible on a typical screen int max = IGV.getInstance().isShowDetailsOnClick() ? 10000 : 30; attributes.printHtml(buf, max); return buf.toString(); } public void setReadingFrame(int offset) { this.readingFrame = offset; } public int getReadingFrame(){ return this.readingFrame; } }