/* * 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.track; import htsjdk.tribble.Tribble; import htsjdk.tribble.index.Index; import htsjdk.tribble.index.IndexFactory; import htsjdk.tribble.util.ParsingUtils; import org.apache.log4j.Logger; import org.broad.igv.Globals; import org.broad.igv.feature.LocusScore; import org.broad.igv.feature.Mutation; import org.broad.igv.feature.Range; import org.broad.igv.feature.genome.Genome; import org.broad.igv.feature.tribble.MUTCodec; import org.broad.igv.feature.tribble.TribbleIndexNotFoundException; import org.broad.igv.util.ResourceLocator; import htsjdk.tribble.Feature; import java.io.IOException; import java.util.*; /** * @author jrobinso * Date: 4/9/13 * Time: 8:45 AM */ public class MutationFeatureSource implements FeatureSource<Mutation> { private static Logger log = Logger.getLogger(MutationFeatureSource.class); String sample; MutationDataManager dataManager; public MutationFeatureSource(String sample, MutationDataManager dataManager) { this.sample = sample; this.dataManager = dataManager; } @Override public Iterator<Mutation> getFeatures(String chr, int start, int end) throws IOException { return dataManager.getFeatures(sample, chr, start, end); } @Override public List<LocusScore> getCoverageScores(String chr, int start, int end, int zoom) { return null; //Not supported for mutation tracks } @Override public int getFeatureWindowSize() { return -1; // Load all features for a given chromosome } @Override public void setFeatureWindowSize(int size) { // Ignored } static public class MutationDataManager { Range currentRange; Map<String, List<Mutation>> featureMap = Collections.synchronizedMap(new HashMap()); TribbleFeatureSource tribbleFeatureSource; ResourceLocator locator; public MutationDataManager(ResourceLocator locator, Genome genome) throws IOException, TribbleIndexNotFoundException { this.tribbleFeatureSource = TribbleFeatureSource.getFeatureSource(locator, genome); this.locator = locator; } public boolean isIndexed() { return this.tribbleFeatureSource.isIndexed(); } synchronized Iterator<Mutation> getFeatures(String trackKey, String chr, int start, int end) throws IOException { if (currentRange == null || !currentRange.contains(chr, start, end)) { Iterator<Feature> features = tribbleFeatureSource.getFeatures(chr, start, end); while (features.hasNext()) { Mutation feat = (Mutation) features.next(); String thisKey = feat.getSampleId(); List<Mutation> keyFeatures = featureMap.get(thisKey); if (keyFeatures == null) { keyFeatures = new ArrayList<Mutation>(); featureMap.put(thisKey, keyFeatures); } keyFeatures.add(feat); currentRange = new Range(chr, start, end); } } List<Mutation> featureList = featureMap.get(trackKey); return featureList == null ? Collections.EMPTY_LIST.iterator() : featureList.iterator(); } public String[] getSamples() { if (this.tribbleFeatureSource.isIndexed()) { // Load the index for meta information. Its already loaded, but not public in the htsjdk class. Index idx = loadIndex(this.locator.getPath()); if (idx != null) { Map<String, String> map = idx.getProperties(); if (map != null && map.containsKey("samples")) { return Globals.commaPattern.split(map.get("samples")); } } } // Try to fetch features from codec. This is to support a deprecated option to // specify sample names in the .mut or .maf file header. MUTCodec codec = new MUTCodec(locator.getPath(), null); return codec.getSamples(); } private Index loadIndex(String path) { try { String indexFile = Tribble.indexFile(path); Index index = null; if (ParsingUtils.resourceExists(indexFile)) { index = IndexFactory.loadIndex(indexFile); } else { // See if the index itself is gzipped indexFile = ParsingUtils.appendToPath(indexFile, ".gz"); if (ParsingUtils.resourceExists(indexFile)) { index = IndexFactory.loadIndex(indexFile); } } return index; } catch (IOException e) { log.error("Error loading index file", e); return null; } } } }