package com.github.lindenb.jvarkit.tools.splitread;
import java.io.File;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.github.lindenb.jvarkit.util.picard.OtherCanonicalAlign;
import com.github.lindenb.jvarkit.util.picard.OtherCanonicalAlignFactory;
import com.github.lindenb.jvarkit.util.picard.SamFileReaderFactory;
import htsjdk.samtools.Cigar;
import htsjdk.samtools.CigarElement;
import htsjdk.samtools.SamReader;
import htsjdk.samtools.SAMRecord;
public class SplitRead {
private static final Logger LOG=Logger.getLogger(SplitRead.class.getSimpleName());
private float maxFractionCommon=0.1f;
private class Fragment
{
String chrom;
int pos;
char strand;
String cigar;
public int compareTo(Fragment other)
{
int i=chrom.compareTo(other.chrom);
if(i!=0) return i;
return pos-other.pos;
}
void print()
{
System.out.print(chrom+"\t"+pos+"\t"+strand+"\t"+cigar);
}
}
private void scanRecord(final SAMRecord record,final OtherCanonicalAlignFactory xPalignFactory) throws Exception
{
if(record.getReadUnmappedFlag()) return;
String xp=record.getStringAttribute("XP");
if(xp==null) return;
LOG.info(xp);
Cigar cigar1=record.getCigar();
int readPos=0;
int readMap1[]=new int[record.getReadLength()];
for(CigarElement ce:cigar1.getCigarElements())
{
switch(ce.getOperator())
{
case I: case S:
{
readPos+=ce.getLength();
break;
}
case M:case X:case EQ:
{
for(int i=0;i< ce.getLength();++i)
{
readMap1[readPos]+=1;
readPos++;
}
break;
}
case P: case H: case D: case N: break;
default: throw new RuntimeException("cigar operator not handled:"+ce.getOperator());
}
}
for(OtherCanonicalAlign xpAln:xPalignFactory.getXPAligns(record))
{
readPos=0;
float common=0f;
for(CigarElement ce:xpAln.getCigarElements())
{
switch(ce.getOperator())
{
case I: case S:
{
readPos+=ce.getLength();
break;
}
case M:case X:case EQ:
{
for(int i=0;i< ce.getLength();++i)
{
if(readMap1[readPos]==1)
{
common++;
}
readPos++;
}
break;
}
case P: case H: case D: case N: break;
default: throw new RuntimeException("cigar operator not handled:"+ce.getOperator());
}
}
float fraction=common/readMap1.length;
if( fraction > this.maxFractionCommon)
{
continue;
}
Fragment f1=new Fragment();
f1.chrom=record.getReferenceName();
f1.pos=record.getAlignmentStart();
f1.strand=(record.getReadNegativeStrandFlag()?'-':'+');
f1.cigar=record.getCigarString();
Fragment f2=new Fragment();
f2.chrom=xpAln.getReferenceName();
f2.pos=xpAln.getAlignmentStart();
f2.strand=xpAln.getReadNegativeStrandFlag()?'-':'+';
f2.cigar=xpAln.getCigarString();
System.out.print(
record.getReadName()+"\t"+
(record.getFirstOfPairFlag()?'F':'R')+"\t"
);
if(f1.compareTo(f2)<0)
{
f1.print();
System.out.print("\t");
f2.print();
}
else
{
f2.print();
System.out.print("\t");
f1.print();
}
System.out.println("\t"+fraction);
}
}
private void scan(SamReader reader) throws Exception
{
OtherCanonicalAlignFactory xpalignFactory=new OtherCanonicalAlignFactory(reader.getFileHeader());
long nrecords=0L;
for(Iterator<SAMRecord> iter=reader.iterator();
iter.hasNext(); )
{
SAMRecord record=iter.next();
++nrecords;
if(nrecords%1E6==0)
{
LOG.info("nRecord:"+nrecords);
System.out.flush();
}
scanRecord(record,xpalignFactory);
}
}
private void run(String[] args)
throws Exception
{
int optind=0;
while(optind< args.length)
{
if(args[optind].equals("-h") ||
args[optind].equals("-help") ||
args[optind].equals("--help"))
{
System.err.println("Pierre Lindenbaum PhD. 2013");
System.err.println("Options:");
System.err.println(" -h help; This screen.");
System.err.println(" -R (reference file) REQUIRED.");
System.err.println(" -L|--level (log level): default:"+LOG.getLevel());
;
}
else if((args[optind].equals("-L") || args[optind].equals("--level")) && optind+1< args.length)
{
LOG.setLevel(Level.parse(args[++optind]));
}
else if(args[optind].equals("--"))
{
optind++;
break;
}
else if(args[optind].startsWith("-"))
{
System.err.println("Unknown option "+args[optind]);
return;
}
else
{
break;
}
++optind;
}
if(optind==args.length)
{
SamReader r=SamFileReaderFactory.mewInstance().openStdin();
scan(r);
r.close();
}
else if(optind+1==args.length)
{
File file=new File(args[optind++]);
SamReader r=SamFileReaderFactory.mewInstance().open(file);
scan(r);
r.close();
}
else
{
System.err.println("illegal number of arguments.");
System.exit(-1);
}
}
public static void main(String[] args) throws Exception
{
LOG.setLevel(Level.OFF);
new SplitRead().run(args);
}
}