All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.maizegenetics.dna.snp.TranslateIndexBuilder Maven / Gradle / Ivy

/*
 *  TranslateIndexBuilder
 * 
 *  Created on Dec 14, 2016
 */
package net.maizegenetics.dna.snp;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *
 * @author Terry Casstevens
 */
public class TranslateIndexBuilder {

    private final TranslateIndex myBase;
    private final int myNumBaseIndices;
    private boolean myHasNegativeIndices = false;
    private boolean myIsUnordered = false;
    private final List myIndicesToKeep = new ArrayList<>();

    private TranslateIndexBuilder(int numBaseIndices) {
        myNumBaseIndices = numBaseIndices;
        myBase = null;
    }

    private TranslateIndexBuilder(TranslateIndex base) {
        myNumBaseIndices = base.numIndices();
        myBase = base;
    }

    public static TranslateIndexBuilder getInstance(int numBaseIndices) {
        return new TranslateIndexBuilder(numBaseIndices);
    }

    public static TranslateIndexBuilder getInstance(TranslateIndex base) {
        return new TranslateIndexBuilder(base);
    }

    public static TranslateIndexBuilder getInstance(int numBaseIndices, TranslateIndex base) {
        if (base == null) {
            return new TranslateIndexBuilder(numBaseIndices);
        } else {
            if (numBaseIndices != base.numIndices()) {
                throw new IllegalArgumentException("TranslateTaxaBuilder: getInstance: numBaseIndices: " + numBaseIndices + " should equal base: " + base.numIndices());
            }
            return new TranslateIndexBuilder(base);
        }
    }

    public static TranslateIndex merge(TranslateIndex base, TranslateIndex translate) {

        if (base == null || translate == null) {
            throw new IllegalArgumentException("TranslateIndexBuilder: merge: base and translate can't be null");
        }

        if (!base.hasTranslations()) {
            return translate;
        }

        int numIndices = translate.numIndices();
        int[] result = new int[numIndices];
        boolean ordered = true;
        int last = -1;
        for (int i = 0; i < numIndices; i++) {
            int temp = translate.translate(i);
            if (temp == -1) {
                result[i] = -1;
                ordered = false;
            } else {
                result[i] = base.translate(temp);
                if (result[i] <= last) {
                    ordered = false;
                }
                last = result[i];
            }
        }

        if (ordered) {
            if (isNoTranslation(result)) {
                if (base.numIndices() == numIndices) {
                    return new TranslateIndex(numIndices, false);
                } else {
                    return new TranslateIndex(numIndices, true);
                }
            } else {
                return new TranslateIndexRedirect(result);
            }
        } else {
            return new TranslateIndexRedirectUnordered(result);
        }

    }

    /**
     * Returns no translation instance.
     *
     * @param numIndices number of indices
     * @return no translation instance
     */
    public static TranslateIndex noTranslation(int numIndices) {
        return new TranslateIndex(numIndices, false);
    }

    public static TranslateIndex orderedTranslation(int[] indexRedirect, TranslateIndex base, int numBaseIndices) {

        int numIndices = indexRedirect.length;

        if (base == null) {
            int[] result = new int[numIndices];
            for (int i = 0; i < numIndices; i++) {
                if (indexRedirect[i] < -1) {
                    throw new IllegalArgumentException("TranslateIndexBuilder: orderedTranslation: ordered translation can't contain negative indices.");
                }
                result[i] = indexRedirect[i];
            }
            Arrays.sort(result);
            if (isNoTranslation(result)) {
                if (numBaseIndices == numIndices) {
                    return new TranslateIndex(numIndices, false);
                } else {
                    return new TranslateIndex(numIndices, true);
                }
            } else {
                return new TranslateIndexRedirect(result);
            }
        } else {
            if (base.numIndices() != numBaseIndices) {
                throw new IllegalArgumentException("TranslateIndexBuilder: orderedTranslation: number of indices in base translation: " + base.numIndices() + " should equal number of base indices: " + numBaseIndices);
            }
            int[] result = new int[numIndices];
            for (int i = 0; i < numIndices; i++) {
                if (indexRedirect[i] < -1) {
                    throw new IllegalArgumentException("TranslateIndexBuilder: orderedTranslation: ordered translation can't contain negative indices.");
                }
                result[i] = base.translate(indexRedirect[i]);
            }
            Arrays.sort(result);
            if (isNoTranslation(result)) {
                if (numBaseIndices == numIndices) {
                    return new TranslateIndex(numIndices, false);
                } else {
                    return new TranslateIndex(numIndices, true);
                }
            } else {
                return new TranslateIndexRedirect(result);
            }
        }

    }

    public static TranslateIndex unorderedTranslation(int[] indicesNewOrder, TranslateIndex base) {

        int numIndices = indicesNewOrder.length;

        if (base == null) {
            int[] result = new int[numIndices];
            for (int i = 0; i < numIndices; i++) {
                if (indicesNewOrder[i] == -1) {
                    result[i] = -1;
                } else if (indicesNewOrder[i] < 0) {
                    throw new IllegalArgumentException("TranslateIndexBuilder: unorderedTranslation: only negative number allowed is -1.");
                } else {
                    result[i] = indicesNewOrder[i];
                }
            }
            return new TranslateIndexRedirectUnordered(result);
        } else {
            if (numIndices != base.numIndices()) {
                throw new IllegalStateException("TranslateIndexBuilder: unorderedTranslation: number of newly ordered indices: " + numIndices + " should equal base num indices: " + base.numIndices());
            }
            int[] result = new int[numIndices];
            for (int i = 0; i < numIndices; i++) {
                if (indicesNewOrder[i] == -1) {
                    result[i] = -1;
                } else if (indicesNewOrder[i] < 0) {
                    throw new IllegalArgumentException("TranslateIndexBuilder: unorderedTranslation: only negative number allowed is -1.");
                } else {
                    result[i] = base.translate(indicesNewOrder[i]);
                }
            }
            return new TranslateIndexRedirectUnordered(result);
        }

    }

    /**
     * Keeps a range of indices from start (inclusive) to end (inclusive)
     *
     * @param start start index
     * @param end end index
     * @param base base translation
     * @param numBaseIndices number of indices in base
     *
     * @return new translation
     */
    public static TranslateIndex range(int start, int end, TranslateIndex base, int numBaseIndices) {

        if (start < 0 || start > end) {
            throw new IllegalArgumentException();
        }

        if (base == null) {
            if (start == 0) {
                int len = end + 1;
                if (len == numBaseIndices) {
                    return new TranslateIndex(len, false);
                } else {
                    return new TranslateIndex(len, true);
                }
            } else {
                return new TranslateIndexRange(start, end);
            }
        } else {
            if (base.numIndices() != numBaseIndices) {
                throw new IllegalArgumentException("TranslateIndexBuilder: range: number of indices in base translation: " + base.numIndices() + " should equal number of base indices: " + numBaseIndices);
            }
            return new TranslateIndexBuilder(base).keepIndices(start, end).build();
        }

    }
    
    public TranslateIndexBuilder unordered() {
        myIsUnordered = true;
        return this;
    }

    /**
     * Keep specified index.
     *
     * @param index index
     *
     * @return this builder
     */
    public TranslateIndexBuilder keepIndex(int index) {
        if (index == -1) {
            myHasNegativeIndices = true;
        } else if (index < 0 || index >= myNumBaseIndices) {
            throw new IllegalArgumentException("TranslateIndexBuilder: keepIndex: index: " + index + " out of range: " + 0 + " to: " + (myNumBaseIndices - 1));
        }
        myIndicesToKeep.add(index);
        return this;
    }

    /**
     * Keeps a range of indices from start (inclusive) to end (inclusive)
     *
     * @param start lower index
     * @param end last index to keep
     *
     * @return this builder
     */
    public TranslateIndexBuilder keepIndices(int start, int end) {
        if (start < 0 || start > end || end >= myNumBaseIndices) {
            throw new IllegalArgumentException();
        }
        for (int i = start; i <= end; i++) {
            myIndicesToKeep.add(i);
        }
        return this;
    }

    public TranslateIndexBuilder keepIndices(int[] indices) {
        for (int current : indices) {
            keepIndex(current);
        }
        return this;
    }

    public int numIndices() {
        return myIndicesToKeep.size();
    }

    private static boolean isNoTranslation(int[] indices) {
        int len = indices.length;
        for (int i = 0; i < len; i++) {
            if (i != indices[i]) {
                return false;
            }
        }
        return true;
    }

    public TranslateIndex build() {

        int numIndicesToKeep = myIndicesToKeep.size();

        int[] indexRedirect = new int[numIndicesToKeep];
        if (myBase == null) {
            for (int i = 0; i < numIndicesToKeep; i++) {
                indexRedirect[i] = myIndicesToKeep.get(i);
            }
        } else {
            for (int i = 0; i < numIndicesToKeep; i++) {
                indexRedirect[i] = myBase.translate(myIndicesToKeep.get(i));
            }
        }

        if (myHasNegativeIndices || myIsUnordered) {
            return new TranslateIndexRedirectUnordered(indexRedirect);
        } else {
            Arrays.sort(indexRedirect);
            if (isNoTranslation(indexRedirect)) {
                if (myNumBaseIndices == indexRedirect.length) {
                    return new TranslateIndex(myNumBaseIndices, false);
                } else {
                    return new TranslateIndex(indexRedirect.length, true);
                }
            } else {
                return new TranslateIndexRedirect(indexRedirect);
            }
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy