package com.github.lindenb.jvarkit.util.bio.fasta;
import java.io.Closeable;
import java.io.File;
import java.util.AbstractList;
import java.util.NoSuchElementException;
import com.github.lindenb.jvarkit.lang.JvarkitException;
import com.github.lindenb.jvarkit.util.log.Logger;
import com.github.lindenb.jvarkit.util.picard.GenomicSequence;
import htsjdk.samtools.SAMSequenceDictionary;
import htsjdk.samtools.SAMSequenceRecord;
import htsjdk.samtools.reference.IndexedFastaSequenceFile;
import htsjdk.samtools.util.CloserUtil;
import htsjdk.samtools.util.IOUtil;
import htsjdk.samtools.util.RuntimeIOException;
public class IndexedGenome
extends AbstractList<GenomicSequence>
implements Closeable {
private static final Logger LOG=Logger.build().prefix("IndexedGenome").make();
public static final String ENV_NAME="REF_PATH";
private final IndexedFastaSequenceFile indexedFastaSequenceFile;
private final SAMSequenceDictionary dict;
private GenomicSequence cached=null;
private IndexedGenome(final IndexedFastaSequenceFile indexedFastaSequenceFile) {
this.indexedFastaSequenceFile=indexedFastaSequenceFile;
this.dict=this.indexedFastaSequenceFile.getSequenceDictionary();
}
public GenomicSequence get(int i)
{
return _get(this.dict.getSequence(i).getSequenceName());
}
private GenomicSequence _get(final String contigName)
{
final SAMSequenceRecord rec=this.dict.getSequence(contigName);
if(rec==null) throw new NoSuchElementException(contigName);
if(this.cached!=null && this.cached.getChrom().equals(contigName)) {
return this.cached;
}
this.cached= new GenomicSequence(this.indexedFastaSequenceFile,rec.getSequenceName());
return this.cached;
}
@Override
public int size() {
return this.dict.size();
}
@Override
public void close() {
CloserUtil.close(this.indexedFastaSequenceFile);
}
public static class Builder
{
private File genomeFile;
private String envName=ENV_NAME;
public Builder setGenomeFile(final File genomeFile) {
this.genomeFile = genomeFile;
return this;
}
public Builder setEnvName(final String envName) {
this.envName = envName;
return this;
}
public IndexedGenome make()
{
File f = this.genomeFile;
if(f==null && envName!=null && !envName.trim().isEmpty()) {
LOG.info("searching reference genome using getenv(\""+envName+"\")");
String ref=System.getenv(envName);
if(ref!=null)
{
f=new File(ref);
}
}
if(f==null) throw new JvarkitException.UserError("REF genome is undefined");
IOUtil.assertFileIsWritable(f);
IndexedFastaSequenceFile idx=null;
try
{
idx = new IndexedFastaSequenceFile(f);
}
catch(final Exception err)
{
LOG.severe(err);
throw new RuntimeIOException(err);
}
final SAMSequenceDictionary dict=idx.getSequenceDictionary();
if(dict==null)
{
CloserUtil.close(idx);
throw new JvarkitException.FastaDictionaryMissing(f.getPath());
}
final IndexedGenome g=new IndexedGenome(idx);
return g;
}
}
public static Builder build() {
return new Builder();
}
}