package com.github.lindenb.jvarkit.util.bio.blast;
import java.util.Iterator;
import gov.nih.nlm.ncbi.blast.Hsp;
public class BlastHspAlignment
implements Iterable<BlastHspAlignment.Align>
{
private final Hsp _hsp;
public enum CigarOperator
{
EQ,X,I,D;
}
public class Align
implements Cloneable
{
private int indexInAlignment=0;
private int query_index ;
private int hit_index;
private Align()
{
}
public int getQueryIndex1()
{
return query_index;
}
public int getHitIndex1()
{
return hit_index;
}
public Hsp getHsp()
{
return BlastHspAlignment.this.getHsp();
}
public int getIndex()
{
return this.indexInAlignment;
}
public char getHitChar()
{
return getHsp().getHspHseq().charAt(getIndex());
}
public char getQueryChar()
{
return getHsp().getHspQseq().charAt(getIndex());
}
public char getMidChar()
{
return getHsp().getHspMidline().charAt(getIndex());
}
public CigarOperator getCigarOperator()
{
//deletion in REF, insert in READ
if(getHitChar()=='-')
{
return CigarOperator.I;
}
//deletion in READ, insert in REF
else if(getQueryChar()=='-')
{
return CigarOperator.D;
}
else if(getMidChar()=='|')
{
return CigarOperator.EQ;
}
else
{
return CigarOperator.X;
}
}
@Override
protected Align clone()
{
Align a=new Align();
a.indexInAlignment=indexInAlignment;
a.hit_index=hit_index;
a.query_index=query_index;
return a;
}
@Override
public boolean equals(Object obj)
{
if(obj==this) return true;
if(obj==null || !(obj instanceof Hsp)) return false;
Align cp=Align.class.cast(obj);
return cp.getHsp()==getHsp() && cp.getIndex()==getIndex();
}
@Override
public int hashCode()
{
return indexInAlignment;
}
@Override
public String toString()
{
return "align["+getIndex()+"]="+getQueryChar()+getMidChar()+getHitChar()+
"/"+
this.getQueryIndex1()+","+this.getHitIndex1();
}
}
public BlastHspAlignment(final Hsp hsp)
{
if(hsp==null) throw new NullPointerException();
this._hsp=hsp;
}
public Hsp getHsp()
{
return _hsp;
}
public static Hsp cloneHsp(Hsp hsp)
{
Hsp h2=new Hsp();
h2.setHspNum(hsp.getHspNum());
h2.setHspBitScore(hsp.getHspBitScore());
h2.setHspScore(hsp.getHspScore());
h2.setHspEvalue(hsp.getHspEvalue());
h2.setHspIdentity(hsp.getHspIdentity());
h2.setHspGaps(hsp.getHspGaps());
h2.setHspPositive(hsp.getHspPositive());
h2.setHspAlignLen(hsp.getHspAlignLen());
h2.setHspQueryFrom(hsp.getHspQueryFrom());
h2.setHspQueryTo(hsp.getHspQueryTo());
h2.setHspQueryFrame(hsp.getHspQueryFrame());
h2.setHspHitFrom(hsp.getHspHitFrom());
h2.setHspHitTo(hsp.getHspHitTo());
h2.setHspHitFrame(hsp.getHspHitFrame());
h2.setHspQseq(hsp.getHspQseq());
h2.setHspHseq(hsp.getHspHseq());
h2.setHspMidline(hsp.getHspMidline());
h2.setHspPatternFrom(hsp.getHspPatternFrom());
h2.setHspPatternTo(hsp.getHspPatternTo());
return h2;
}
private int alignLen=-1;
public int getAlignLength()
{
if(this.alignLen<0)
{
if(getHsp().getHspAlignLen()!=null)
{
this.alignLen=Integer.parseInt(getHsp().getHspAlignLen());
}
else
{
this.alignLen=getHsp().getHspMidline().length();
}
}
return this.alignLen;
}
private int queryFrom=-1;
public int getQueryFrom1()
{
if(this.queryFrom<0)
{
this.queryFrom=Integer.parseInt(getHsp().getHspQueryFrom());
}
return this.queryFrom;
}
private int queryTo=-1;
public int getQueryTo1()
{
if(this.queryTo<0)
{
this.queryTo=Integer.parseInt(getHsp().getHspQueryTo());
}
return this.queryTo;
}
private int hitFrom=-1;
public int getHitFrom1()
{
if(this.hitFrom<0)
{
this.hitFrom=Integer.parseInt(getHsp().getHspHitFrom());
}
return this.hitFrom;
}
private int hitTo=-1;
public int getHitTo1()
{
if(this.hitTo<0)
{
this.hitTo=Integer.parseInt(getHsp().getHspHitTo());
}
return this.hitTo;
}
private int hitShift()
{
return getHitFrom1()>getHitTo1()?-1:1;
}
public boolean isPlusPlus()
{
return hitShift()==1;
}
public final boolean isPlusMinus()
{
return !isPlusPlus();
}
@Override
public Iterator<Align> iterator()
{
return new MyIterator();
}
private class MyIterator
implements Iterator<BlastHspAlignment.Align>
{
private Align curr;
MyIterator()
{
curr=new Align();
curr.query_index = owner().getQueryFrom1();
curr.hit_index = owner().getHitFrom1();
curr.indexInAlignment=0;
}
BlastHspAlignment owner()
{
return BlastHspAlignment.this;
}
@Override
public boolean hasNext()
{
return curr.indexInAlignment< owner().getAlignLength();
}
@Override
public Align next()
{
if(curr.indexInAlignment >= owner().getAlignLength())
{
throw new IllegalStateException();
}
Align ret= curr.clone();
char ch= curr.getHitChar();
char cq= curr.getQueryChar();
if(ch!='-' && ch!=' ')
{
curr.hit_index+=hitShift();
}
if(cq!='-' && cq!=' ')
{
curr.query_index++;
}
++curr.indexInAlignment;
return ret;
}
@Override
public void remove()
{
throw new UnsupportedOperationException();
}
}
}