/* * Copyright (c) 2012 The 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 htsjdk.variant.variantcontext; import htsjdk.variant.vcf.VCFConstants; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * Common utility routines for VariantContext and Genotype * * @author depristo */ public final class CommonInfo { public static final double NO_LOG10_PERROR = 1.0; private static Set<String> NO_FILTERS = Collections.emptySet(); private static Map<String, Object> NO_ATTRIBUTES = Collections.unmodifiableMap(new HashMap<String, Object>()); private double log10PError = NO_LOG10_PERROR; private String name = null; private Set<String> filters = null; private Map<String, Object> attributes = NO_ATTRIBUTES; public CommonInfo(String name, double log10PError, Set<String> filters, Map<String, Object> attributes) { this.name = name; setLog10PError(log10PError); this.filters = filters; if ( attributes != null && ! attributes.isEmpty() ) { this.attributes = attributes; } } /** * @return the name */ public String getName() { return name; } /** * Sets the name * * @param name the name associated with this information */ public void setName(String name) { if ( name == null ) throw new IllegalArgumentException("Name cannot be null " + this); this.name = name; } // --------------------------------------------------------------------------------------------------------- // // Filter // // --------------------------------------------------------------------------------------------------------- public Set<String> getFiltersMaybeNull() { return filters; } public Set<String> getFilters() { return filters == null ? NO_FILTERS : Collections.unmodifiableSet(filters); } public boolean filtersWereApplied() { return filters != null; } public boolean isFiltered() { return filters == null ? false : filters.size() > 0; } public boolean isNotFiltered() { return ! isFiltered(); } public void addFilter(String filter) { if ( filters == null ) // immutable -> mutable filters = new HashSet<String>(); if ( filter == null ) throw new IllegalArgumentException("BUG: Attempting to add null filter " + this); if ( getFilters().contains(filter) ) throw new IllegalArgumentException("BUG: Attempting to add duplicate filter " + filter + " at " + this); filters.add(filter); } public void addFilters(Collection<String> filters) { if ( filters == null ) throw new IllegalArgumentException("BUG: Attempting to add null filters at" + this); for ( String f : filters ) addFilter(f); } // --------------------------------------------------------------------------------------------------------- // // Working with log error rates // // --------------------------------------------------------------------------------------------------------- public boolean hasLog10PError() { return getLog10PError() != NO_LOG10_PERROR; } /** * @return the -1 * log10-based error estimate */ public double getLog10PError() { return log10PError; } public double getPhredScaledQual() { return getLog10PError() * -10; } public void setLog10PError(double log10PError) { if ( log10PError > 0 && log10PError != NO_LOG10_PERROR) throw new IllegalArgumentException("BUG: log10PError cannot be > 0 : " + this.log10PError); if ( Double.isInfinite(this.log10PError) ) throw new IllegalArgumentException("BUG: log10PError should not be Infinity"); if ( Double.isNaN(this.log10PError) ) throw new IllegalArgumentException("BUG: log10PError should not be NaN"); this.log10PError = log10PError; } // --------------------------------------------------------------------------------------------------------- // // Working with attributes // // --------------------------------------------------------------------------------------------------------- public void clearAttributes() { attributes = new HashMap<String, Object>(); } /** * @return the attribute map */ public Map<String, Object> getAttributes() { return Collections.unmodifiableMap(attributes); } // todo -- define common attributes as enum public void setAttributes(Map<String, ?> map) { clearAttributes(); putAttributes(map); } public void putAttribute(String key, Object value) { putAttribute(key, value, false); } public void putAttribute(String key, Object value, boolean allowOverwrites) { if ( ! allowOverwrites && hasAttribute(key) ) throw new IllegalStateException("Attempting to overwrite key->value binding: key = " + key + " this = " + this); if ( attributes == NO_ATTRIBUTES ) // immutable -> mutable attributes = new HashMap<String, Object>(); attributes.put(key, value); } public void removeAttribute(String key) { if ( attributes == NO_ATTRIBUTES ) // immutable -> mutable attributes = new HashMap<String, Object>(); attributes.remove(key); } public void putAttributes(Map<String, ?> map) { if ( map != null ) { // for efficiency, we can skip the validation if the map is empty if ( attributes.size() == 0 ) { if ( attributes == NO_ATTRIBUTES ) // immutable -> mutable attributes = new HashMap<String, Object>(); attributes.putAll(map); } else { for ( Map.Entry<String, ?> elt : map.entrySet() ) { putAttribute(elt.getKey(), elt.getValue(), false); } } } } public boolean hasAttribute(String key) { return attributes.containsKey(key); } public int getNumAttributes() { return attributes.size(); } /** * @param key the attribute key * * @return the attribute value for the given key (or null if not set) */ public Object getAttribute(String key) { return attributes.get(key); } public Object getAttribute(String key, Object defaultValue) { if ( hasAttribute(key) ) return attributes.get(key); else return defaultValue; } public String getAttributeAsString(String key, String defaultValue) { Object x = getAttribute(key); if ( x == null ) return defaultValue; if ( x instanceof String ) return (String)x; return String.valueOf(x); // throws an exception if this isn't a string } public int getAttributeAsInt(String key, int defaultValue) { Object x = getAttribute(key); if ( x == null || x == VCFConstants.MISSING_VALUE_v4 ) return defaultValue; if ( x instanceof Integer ) return (Integer)x; return Integer.valueOf((String)x); // throws an exception if this isn't a string } public double getAttributeAsDouble(String key, double defaultValue) { Object x = getAttribute(key); if ( x == null ) return defaultValue; if ( x instanceof Double ) return (Double)x; if ( x instanceof Integer ) return (Integer)x; return Double.valueOf((String)x); // throws an exception if this isn't a string } public boolean getAttributeAsBoolean(String key, boolean defaultValue) { Object x = getAttribute(key); if ( x == null ) return defaultValue; if ( x instanceof Boolean ) return (Boolean)x; return Boolean.valueOf((String)x); // throws an exception if this isn't a string } // public String getAttributeAsString(String key) { return (String.valueOf(getExtendedAttribute(key))); } // **NOTE**: will turn a null Object into the String "null" // public int getAttributeAsInt(String key) { Object x = getExtendedAttribute(key); return x instanceof Integer ? (Integer)x : Integer.valueOf((String)x); } // public double getAttributeAsDouble(String key) { Object x = getExtendedAttribute(key); return x instanceof Double ? (Double)x : Double.valueOf((String)x); } // public boolean getAttributeAsBoolean(String key) { Object x = getExtendedAttribute(key); return x instanceof Boolean ? (Boolean)x : Boolean.valueOf((String)x); } // public Integer getAttributeAsIntegerNoException(String key) { try {return getAttributeAsInt(key);} catch (Exception e) {return null;} } // public Double getAttributeAsDoubleNoException(String key) { try {return getAttributeAsDouble(key);} catch (Exception e) {return null;} } // public String getAttributeAsStringNoException(String key) { if (getExtendedAttribute(key) == null) return null; return getAttributeAsString(key); } // public Boolean getAttributeAsBooleanNoException(String key) { try {return getAttributeAsBoolean(key);} catch (Exception e) {return null;} } }