-
Notifications
You must be signed in to change notification settings - Fork 245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Yf add interval list codec #1327
Changes from 5 commits
df6d0c0
841bad3
6f75f7b
d5e317f
d71b5c7
ffb6dc5
cdd5501
5ee7723
0c7b528
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,10 @@ | |
/** | ||
* Interface allows for implementations that read lines from a String, an ASCII file, or somewhere else. | ||
*/ | ||
public interface LineReader extends Closeable{ | ||
public interface LineReader extends Closeable { | ||
|
||
// value to return in call to peek, if eof has been reached. | ||
int EOF_VALUE = -1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs javadoc, and |
||
|
||
/** | ||
* Read a line and remove the line terminator | ||
|
@@ -43,7 +46,7 @@ public interface LineReader extends Closeable{ | |
|
||
/** | ||
* Non-destructive one-character look-ahead. | ||
* @return If not eof, the next character that would be read. If eof, -1. | ||
* @return If not eof, the next character that would be read. If eof, {@value EOF_VALUE}. | ||
*/ | ||
int peek(); | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,164 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* Copyright (c) 2019, The Broad Institute | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* Permission is hereby granted, free of charge, to any person | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* obtaining a copy of this software and associated documentation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* files (the "Software"), to deal in the Software without | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* restriction, including without limitation the rights to use, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* copies of the Software, and to permit persons to whom the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* Software is furnished to do so, subject to the following | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* conditions: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* The above copyright notice and this permission notice shall be | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* included in all copies or substantial portions of the Software. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* OTHER DEALINGS IN THE SOFTWARE. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
package htsjdk.tribble.IntervalList; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import htsjdk.samtools.*; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import htsjdk.samtools.util.FormatUtil; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import htsjdk.samtools.util.Interval; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import htsjdk.samtools.util.LineReader; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import htsjdk.samtools.util.Log; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import htsjdk.tribble.AsciiFeatureCodec; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import htsjdk.tribble.TribbleException; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import htsjdk.tribble.annotation.Strand; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import htsjdk.tribble.readers.LineIterator; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* A tribble codec for IntervalLists. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* Also contains the parsing code for the non-tribble parsing of IntervalLists | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public class IntervalListCodec extends AsciiFeatureCodec<Interval> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private final Log log = Log.getInstance(IntervalListCodec.class); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private SAMSequenceDictionary dictionary; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public IntervalListCodec() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this(null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public IntervalListCodec(final SAMSequenceDictionary dict) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
super(Interval.class); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
dictionary = dict; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
String lastSeq = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private Interval parseIntervalString(final String line, final SAMSequenceDictionary dict) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final int SEQUENCE_POS = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final int START_POS = 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final int END_POS = 2; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final int STRAND_POS = 3; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final int NAME_POS = 4; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final FormatUtil format = new FormatUtil(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Make sure we have the right number of fields | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final String[] fields = line.split("\t"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (fields.length != 5) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw new TribbleException("Invalid interval record contains " + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fields.length + " fields: " + line); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Then parse them out | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
String seq = fields[SEQUENCE_POS]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (seq.equals(lastSeq)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
seq = lastSeq; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lastSeq = seq; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know you just moved this code from elsewhere, but I assume this is just cheap interning ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should be in master already. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, was just curious what is was doing. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final int start = format.parseInt(fields[START_POS]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final int end = format.parseInt(fields[END_POS]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (start < 1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw new IllegalArgumentException("Coordinate less than 1: start value of " + start + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
" is less than 1 and thus illegal"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (start > end + 1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw new IllegalArgumentException("Start value of " + start + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
" is greater than end + 1 for end of value: " + end + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
". I'm afraid I cannot let you do that."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Strand strand = Strand.decode(fields[STRAND_POS]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (strand==Strand.NONE) throw new IllegalArgumentException("Invalid strand field: " + fields[STRAND_POS]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final String name = fields[NAME_POS]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final Interval interval = new Interval(seq, start, end, strand==Strand.NEGATIVE, name); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final SAMSequenceRecord sequence = dict.getSequence(seq); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (sequence == null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
log.warn("Ignoring interval for unknown reference: " + interval); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final int sequenceLength = sequence.getSequenceLength(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (sequenceLength > 0 && sequenceLength < end) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw new IllegalArgumentException("interval with end: " + end + " extends beyond end of sequence with length: " + sequenceLength); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return interval; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public Interval decode(final String line) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (line.startsWith("@")) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (line.trim().isEmpty()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// our header cannot be null, we need the dictionary from the header | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (dictionary == null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw new TribbleException("IntervalList dictionary cannot be null when decoding a record"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return parseIntervalString(line, dictionary); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public Object readActualHeader(LineIterator lineIterator) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final SAMTextHeaderCodec headerCodec = new SAMTextHeaderCodec(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
final SAMFileHeader header = headerCodec.decode(new LineReader() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int lineNo = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public String readLine() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lineNo++; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return lineIterator.next(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public int getLineNumber() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return lineNo; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public int peek() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return lineIterator.hasNext() ? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lineIterator.peek().charAt(0) : | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
LineReader.EOF_VALUE; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public void close() { } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, "IntervalListCodec"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
dictionary = header.getSequenceDictionary(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return header; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks. I tried that first and failed...this is better. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public boolean canDecode(String s) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return s.endsWith(".interval_list"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally
IntervalListCodec
wouldn't have to provide this constructor, since the codec should really get the dictionary from it's input stream directly. Also, the code above that parses out the header lines is redundant with code thats already in the codec; the codec implementation is better because it doesn't require reading the entire header into a string that is then re-parsed. But, I don't see a way to bridge from theBufferedReader
to the codec. We might want to think about deprecatingfromReader(final BufferedReader in)
; it would be easy to replace it with a (stream/file/path) overload that could use the codec directly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that there's an action item here...please correct me if I'm wrong :-)