001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.bio.symbol;
022
023import java.util.HashMap;
024import java.util.Map;
025
026import org.biojava.bio.seq.DNATools;
027
028/**
029 * <p>
030 * A factory that is used to maintain associations between alphabets and
031 * preferred bit-packings for them.
032 * </p>
033 *
034 * <p>
035 * There are many ways to pack the symbols for an alphabet as binary.
036 * Different applications will wish to have different representations for
037 * reasons such as integration with external formats, whether to store
038 * ambiguity or not and what algorithms may be used on the bit-packed
039 * representation. Also, it has utility methods to arrange the bit-strings
040 * for symbols within a Java int primitive.
041 * </p>
042 *
043 * @author Matthew Pocock
044 * @author Thomas Down
045 */
046public class PackingFactory {
047  private final static Map packForAlpha;
048
049  static {
050    packForAlpha = new HashMap();
051
052  }
053
054  /**
055   * Get the default packing for an alphabet.
056   *
057   * @param alpha  the FiniteAlphabet that will be bit-packed
058   * @param ambiguity  true if the packing should store ambiguity and false
059   *                   if it can discard ambiguity information
060   * @throws IllegalAlphabetException if this combination of alphabet and
061   *                   ambiguity can not be handled
062   **/
063  public static Packing getPacking(FiniteAlphabet alpha, boolean ambiguity)
064  throws IllegalAlphabetException {
065    Packing pack = (Packing) packForAlpha.get(alpha);
066    if(pack == null) {
067      if(alpha == DNATools.getDNA()) {
068        if(ambiguity) {
069          pack = new DNAAmbPack();
070        } else {
071          pack = new DNANoAmbPack(DNATools.a());
072        }
073      } else {
074        if(ambiguity) {
075          // can't handle this in the general case
076          throw new IllegalAlphabetException();
077        } else {
078          pack = new IndexedNoAmbPack(AlphabetManager.getAlphabetIndex(alpha));
079        }
080      }
081    }
082    return pack;
083  }
084
085  public static int primeWord(
086    SymbolList symList,
087    int wordLength,
088    Packing packing
089  ) throws IllegalSymbolException {
090    int word = 0;
091    for(int i = 0; i < wordLength; i++) {
092      int p = packing.pack(symList.symbolAt(i+1));
093      word |= (int) ((int) p << (int) (i * packing.wordSize()));
094    }
095    return word;
096  }
097
098  public static int nextWord(
099    SymbolList symList,
100    int word,
101    int offset,
102    int wordLength,
103    Packing packing
104  ) throws IllegalSymbolException {
105    word = word >> (int) packing.wordSize();
106    int p = packing.pack(symList.symbolAt(offset));
107    word |= (int) p << ((int) (wordLength - 1) * packing.wordSize());
108    return word;
109  }
110
111  public static void binary(long val) {
112    for(int i = 63; i >= 0; i--) {
113      System.out.print( ((((val >> i) & 1) == 1) ? 1 : 0) );
114    }
115    System.out.println();
116  }
117  public static void binary(int val) {
118    for(int i = 31; i >= 0; i--) {
119      System.out.print( ((((val >> i) & 1) == 1) ? 1 : 0) );
120    }
121    System.out.println();
122  }
123}
124