/*
 *This library is free software; you can redistribute it and/or
 *modify it under the terms of the GNU Lesser General Public
 *License as published by the Free Software Foundation; either
 *version 2.1 of the License, or (at your option) any later version.
 *
 *This library is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *Lesser General Public License for more details.
 *
 *You should have received a copy of the GNU Lesser General Public
 *License along with this library; if not, write to the Free Software
 *Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/* 
 * This software was written by Phillip Lord (p.lord@hgmp.mrc.ac.uk)
 * whilst at the University of Manchester as a Pfizer post-doctoral 
 * Research Fellow. 
 *
 * The initial code base is copyright by Pfizer, or the University
 * of Manchester. Modifications to the initial code base are copyright
 * of their respective authors, or their employers as appropriate. 
 * Authorship of the modifications may be determined from the ChangeLog
 * placed at the end of this file
 */

package uk.ac.man.bioinf.sequence.alignment; // Package name inserted by JPack
import uk.ac.man.bioinf.sequence.Element;


/**
 * AlignmentColumn.java
 *
 * The Sequence and SequenceAlignment classes have been created to be fail-fast. They
 * throw exceptions if attempts are made to access and element outside
 * of the range of the sequence. Additionally the alignment allows
 * sequences to start at any place within the alignment which is very
 * nice, but has the disadvantage of being a little fiddly to use in some
 * circumstances. This class addresses this problem. Essentially it is
 * a mask over a sequence alignment. It can be moved to any column of
 * the alignment, and will then return the elements down that
 * column. It takes care of the offsets, and returns a simple gap
 * Element if a request is made for an Element from before a sequence
 * starts or after a sequence finishes, so long as the row > 0 and <
 * alignment.getLength(). 
 *
 * Created: Wed Jun  7 14:23:43 2000
 *
 * @author Phillip Lord
 * @version $Id: AlignmentColumn.java,v 1.3 2001/04/11 17:04:43 lord Exp $
 */

public class AlignmentColumn 
{
  
  private SequenceAlignment alignment;
  // init this to 1 as it makes more sense that 0. 
  private int column = 1;
  
  public AlignmentColumn()
  {
  }
  
  public AlignmentColumn( SequenceAlignment alignment )
  {
    this();
    setAlignment( alignment );
  }
  
  public void setAlignment( SequenceAlignment alignment )
  {
    this.alignment = alignment;
  }
  
  public SequenceAlignment getAlignment()
  {
    return alignment;
  }
  
  public void setColumn( int column )
  {
    this.column = column;
  }
  
  public int getColumn()
  {
    return column;
  }
  
  /**
   * Get the element for this column at the given row. This will
   * return a Gap element if in front or after the sequence. 
   * @param row the row
   * @throws NoSuchSequenceException if row < 1 or row > getNumberSequences()
   * @throws IllegalStateException if the alignment has not been set
   * @return the element
   */
  public Element getElementAtRow( int row ) throws NoSuchSequenceException, IllegalStateException
  {
    int alignmentHeight;
    try{
      alignmentHeight = alignment.getNumberSequences();
    }
    catch( NullPointerException npe ){
      throw new IllegalStateException( "No alignment given" );
    }
    
    // are we in front of the sequence (also throws
    // NoSuchSequenceException if out of bounds) 
    int inset = alignment.getInset( row );
    if( column < inset + 1 ){
      //System.out.println( "Before the start of the gapped sequence " );
      return Gap.GAP;
    }
    
    GappedSequence sequence = alignment.getSequenceAt( row );
    if( column > sequence.getGappedLength() + inset ){
      //System.out.println( "Off the end of the gapped sequence therefore gap" );
      return Gap.GAP;
    }
    
    return sequence.getGappedElementAt( column - inset );
  }
} // AlignmentColumn



/*
 * ChangeLog
 * $Log: AlignmentColumn.java,v $
 * Revision 1.3  2001/04/11 17:04:43  lord
 * Added License agreements to all code
 *
 * Revision 1.2  2000/11/27 18:18:02  lord
 * Cosmetic
 *
 * Revision 1.1  2000/06/13 11:08:53  lord
 * Initial checkin
 *
 */
