Package org.broad.igv.plugin.mongocollab

Source Code of org.broad.igv.plugin.mongocollab.MongoFeatureSource

/*
* Copyright (c) 2007-2012 The Broad Institute, Inc.
* SOFTWARE COPYRIGHT NOTICE
* This software and its documentation are the copyright of the Broad Institute, Inc. All rights are reserved.
*
* This software is supplied without any warranty or guaranteed support whatsoever. The Broad Institute is not responsible for its use, misuse, or functionality.
*
* This software is licensed under the terms of the GNU Lesser General Public License (LGPL),
* Version 2.1 which is available at http://www.opensource.org/licenses/lgpl-2.1.php.
*/

package org.broad.igv.plugin.mongocollab;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import org.apache.log4j.Logger;
import org.broad.igv.dev.api.NamedFeatureSearcher;
import org.broad.igv.feature.FeatureUtils;
import org.broad.igv.feature.LocusScore;
import org.broad.igv.feature.NamedFeature;
import org.broad.igv.track.FeatureSource;
import org.broad.igv.track.FeatureTrack;
import org.broad.igv.track.Track;
import org.broad.igv.ui.action.SearchCommand;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
* User: jacob
* Date: 2012-Dec-14
*/
public class MongoFeatureSource implements FeatureSource<DBFeature.IGVFeat>, NamedFeatureSearcher {

    private int featureWindowSize = 1000000;

    private DBCollection collection;
    private boolean hasLocusIndex = false;

    private static Logger log = Logger.getLogger(MongoCollabPlugin.class);

    public MongoFeatureSource(DBCollection collection, boolean buildLocusIndex) {
        this.collection = collection;
        this.collection.setObjectClass(DBFeature.class);
        checkForLocusIndex(buildLocusIndex);
    }

    boolean hasLocusIndex(){
        return this.hasLocusIndex;
    }

    /**
     * Check to see if we have an index useful for queries
     * @param buildIndex Whether to build locus index if not found
     */
    private void checkForLocusIndex(boolean buildIndex){
        if(buildIndex){
            ensureLocusIndex(collection);
        }
        //Check to see if we have the index we want
        List<DBObject> indexes = collection.getIndexInfo();
        DBObject neededFields = getLocusIndexKeys();
        for(DBObject index: indexes){

            boolean isMatchingIndex = true;
            DBObject indexKey = (DBObject) index.get("key");
            for(String key: neededFields.keySet()){
                boolean hasKey = indexKey.containsField(key);
                if(!hasKey){
                    isMatchingIndex = false;
                    break;
                }
                Object value = indexKey.get(key);
                boolean equals = neededFields.get(key).equals(value);
                isMatchingIndex &= equals;
            }

            if(isMatchingIndex) {
                this.hasLocusIndex = true;
                break;
            }
        }
    }


    private DBObject createQueryObject(String chr, int start, int end){
        BasicDBObject query = new BasicDBObject("Chr", chr);

        //Only query over given interval
        //See http://docs.mongodb.org/manual/tutorial/query-documents/
        query.append("Start", new BasicDBObject("$lte", end));
        query.append("End", new BasicDBObject("$gte", start));

        return query;
    }

    /**
     * Return the key/value pairs for indexing
     * Store these as doubles for easier comparison, MongoDB stores everything
     * as a double in the DB
     * @return
     */
    private DBObject getLocusIndexKeys(){
        BasicDBObject indexKeys = new BasicDBObject("Chr", 1.0d);
        indexKeys.append("Start", 1.0d);
        indexKeys.append("End", 1.0d);
        return indexKeys;
    }

    /**
     * Ensures there is an index on Chr, Start, and End
     * To speed queries
     * See http://docs.mongodb.org/manual/reference/method/db.collection.ensureIndex/#db.collection.ensureIndex
     * @param collection
     */
    private void ensureLocusIndex(DBCollection collection){
        collection.ensureIndex(getLocusIndexKeys());
    }

    @Override
    public Iterator<DBFeature.IGVFeat> getFeatures(String chr, int start, int end) throws IOException {
         return getFeatures(createQueryObject(chr, start, end), 0).iterator();
    }

    @Override
    public Collection<? extends NamedFeature> search(String name, int limit) {
        BasicDBObject dbObj = new BasicDBObject("UpperName", name.toUpperCase());
        try {
            return getFeatures(dbObj, limit);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     *
     * @param queryObject
     * @param limit Limitation on the number of results returned. Setting to 0 is equivalent to unlimited
     * @return
     * @throws IOException
     */
    private Collection<DBFeature.IGVFeat> getFeatures(DBObject queryObject, int limit) throws IOException{
        DBCursor cursor = this.collection.find(queryObject);
        cursor.limit(limit >= 0 ? limit : 0);

        //Sort by increasing start value
        //Only do this if we have an index, otherwise might be too memory intensive
        if(hasLocusIndex){
            cursor.sort(new BasicDBObject("Start", 1));
        }
        boolean isSorted = true;
        int lastStart = -1;

        List<DBFeature.IGVFeat> features = new ArrayList<DBFeature.IGVFeat>();
        while (cursor.hasNext()) {
            DBObject obj = cursor.next();
            DBFeature feat = (DBFeature) obj;
            features.add(feat.createIGVFeature());
            isSorted &= feat.getStart() >= lastStart;
            lastStart = feat.getStart();
        }

        if(!isSorted){
            FeatureUtils.sortFeatureList(features);
        }

        return features;
    }


    @Override
    public List<LocusScore> getCoverageScores(String chr, int start, int end, int zoom) {
        return null;
    }

    @Override
    public int getFeatureWindowSize() {
        return featureWindowSize;
    }

    @Override
    public void setFeatureWindowSize(int size) {
        this.featureWindowSize = size;
    }

    DBCollection getCollection(){
        return this.collection;
    }

    public static FeatureTrack loadFeatureTrack(MongoCollabPlugin.Locator locator, List<Track> newTracks) {

        DBCollection collection = MongoCollabPlugin.getCollection(locator);
        //TODO Make this more flexible
        collection.setObjectClass(DBFeature.class);
        MongoFeatureSource source = new MongoFeatureSource(collection, locator.buildLocusIndex);
        FeatureTrack track = new MongoFeatureTrack(collection.getFullName(), collection.getName(), source);
        SearchCommand.registerNamedFeatureSearcher(source);
        newTracks.add(track);
        track.setMargin(0);
        return track;
    }
}
TOP

Related Classes of org.broad.igv.plugin.mongocollab.MongoFeatureSource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.