Browse Source

support for options in basesWith

Currently, only one option is supported, which provides
cigar_after and cigar_before properties for each PerBaseInfo.
remotes/georgeg/no_streams
lomereiter 10 years ago
parent
commit
aaddb9333c
  1. 71
      bio/bam/baseinfo.d
  2. 20
      test/unittests.d

71
bio/bam/baseinfo.d

@ -32,6 +32,12 @@ import std.conv;
import std.traits;
import std.typetuple;
///
enum Option
{
cigarExtra /// adds 'cigar_before' and 'cigar_after' properties to each base
}
///
struct MixinArg(T, string Tag) {
T value;
@ -45,7 +51,30 @@ MixinArg!(T, Tag) arg(string Tag, T)(T value) {
return MixinArg!(T, Tag)(value);
}
struct PerBaseInfo(R, Tags...) {
template staticFilter(alias P, T...)
{
static if (T.length == 0)
alias TypeTuple!() staticFilter;
else static if (P!(T[0]))
alias TypeTuple!(T[0], staticFilter!(P, T[1..$])) staticFilter;
else
alias staticFilter!(P, T[1..$]) staticFilter;
}
template isTag(alias argument)
{
enum isTag = is(typeof(argument) == string);
}
template isOption(alias argument)
{
enum isOption = is(typeof(argument) == Option);
}
struct PerBaseInfo(R, TagsAndOptions...) {
alias staticFilter!(isTag, TagsAndOptions) Tags;
alias staticFilter!(isOption, TagsAndOptions) Options;
private alias TypeTuple!("CIGAR", Tags) Extensions;
@ -85,7 +114,7 @@ struct PerBaseInfo(R, Tags...) {
private static string getResultProperties(Exts...)() {
char[] result;
foreach (ext; Exts)
result ~= "mixin " ~ ext ~ "baseInfo!R.resultProperties;".dup;
result ~= "mixin " ~ ext ~ "baseInfo!(R, Options).resultProperties;".dup;
return cast(string)result;
}
@ -99,23 +128,31 @@ struct PerBaseInfo(R, Tags...) {
return to!string(base);
}
bool opEquals(T)(T base) if (is(Unqual!T == Base))
bool opEquals(T)(T base) const
if (is(Unqual!T == Base))
{
return this.base == base;
}
bool opEquals(T)(T result) if (is(Unqual!T == Result))
bool opEquals(T)(T result) const
if (is(Unqual!T == Result))
{
return this == result;
}
bool opEquals(T)(T base) const
if (is(Unqual!T == char) || is(Unqual!T == dchar))
{
return this.base == base;
}
mixin(getResultProperties!Extensions());
}
private static string getRangeMethods(Exts...)() {
char[] result;
foreach (ext; Exts)
result ~= "mixin " ~ ext ~ "baseInfo!R.rangeMethods " ~ ext ~ ";".dup;
result ~= "mixin " ~ ext ~ "baseInfo!(R, Options).rangeMethods " ~ ext ~ ";".dup;
return cast(string)result;
}
@ -163,8 +200,8 @@ struct PerBaseInfo(R, Tags...) {
moveToNextBase();
}
PerBaseInfo!(R, Tags) save() @property {
PerBaseInfo!(R, Tags) r = void;
PerBaseInfo save() @property {
PerBaseInfo r = void;
r._read = _read.dup;
r._seq = _seq.save;
r._rev = _rev;
@ -203,16 +240,16 @@ struct PerBaseInfo(R, Tags...) {
///
/// basesWith!"FZ"(arg!"flowOrder"(flow_order), arg!"keySequence"(key_sequence));
///
template basesWith(Tags...) {
template basesWith(TagsAndOptions...) {
auto basesWith(R, Args...)(R read, Args args) {
return PerBaseInfo!(R, Tags)(read, args);
return PerBaseInfo!(R, TagsAndOptions)(read, args);
}
}
/// Provides additional properties
/// * reference_base
/// * md_operation
template MDbaseInfo(R) {
template MDbaseInfo(R, Options...) {
mixin template resultProperties() {
/// If current CIGAR operation is reference consuming,
@ -327,7 +364,7 @@ template MDbaseInfo(R) {
}
/// Provides additional property $(D flow_call).
template FZbaseInfo(R) {
template FZbaseInfo(R, Options...) {
mixin template resultProperties() {
/// Current flow call
@ -421,11 +458,13 @@ template FZbaseInfo(R) {
/// * position
/// * cigar_operation
/// * cigar_operation_offset
template CIGARbaseInfo(R) {
template CIGARbaseInfo(R, Options...) {
mixin template resultProperties() {
version(CigarExtra)
enum CigarExtraProperties = staticIndexOf!(Option.cigarExtra, Options) != -1;
static if (CigarExtraProperties)
{
/// Current CIGAR operation
CigarOperation cigar_operation() @property {
@ -466,7 +505,7 @@ template CIGARbaseInfo(R) {
int _operation_index = void;
uint _reference_position = void;
uint _cigar_operation_offset = void;
version (CigarExtra)
static if (CigarExtraProperties)
{
ReversableRange!(identity, const(CigarOperation)[]) _cigar = void;
}
@ -479,6 +518,8 @@ template CIGARbaseInfo(R) {
mixin template rangeMethods() {
enum CigarExtraProperties = staticIndexOf!(Option.cigarExtra, Options) != -1;
private {
CigarOperation _current_cigar_op = void;
int _index = void;
@ -507,7 +548,7 @@ template CIGARbaseInfo(R) {
void populate(Result)(ref Result result) {
result._reference_position = _ref_pos;
result._cigar_operation_offset = _at;
version (CigarExtra)
static if (CigarExtraProperties)
{
result._cigar = _cigar;
result._operation_index = _index;

20
test/unittests.d

@ -50,6 +50,7 @@ import std.array;
import std.conv;
import std.exception;
import std.math;
import std.typetuple;
unittest {
@ -354,10 +355,13 @@ unittest {
auto read = reads[1];
assert(!read.is_reverse_strand);
auto bases = basesWith!("FZ", "MD")(read,
arg!"flowOrder"(flow_order),
arg!"keySequence"(key_sequence));
alias TypeTuple!("FZ", "MD", Option.cigarExtra) Options;
auto bases = basesWith!Options(read,
arg!"flowOrder"(flow_order),
arg!"keySequence"(key_sequence));
assert(equal(bases.front.cigar_after, read.cigar[1 .. $]));
assert(equal(drop(map!"a.reference_base"(bases.save), 191),
"-CCCGATTGGTCGTTGCTTTACGCTGATTGGCGAGTCCGGGGAACGTACCTTTGCTATCAGTCCAGGCCACATGAACCAGCTGCGGGCTGAAAGCATTCCGGAAGATGTGATTGCCGGACCTCGGCACTGGTTCTCACCTCATATCTGGTGCGTTGCAAGCCGGGTGAACCCATGCCGGAAGCACCATGAAAGCCATTGAGTACGCGAAGAAATATA"));
assert(equal(bases.save, read.sequence));
@ -385,13 +389,13 @@ unittest {
if (r.is_unmapped) continue;
if (r.cigar.length == 0) continue;
if (r.is_reverse_strand) {
bases = basesWith!("FZ", "MD")(r, arg!"flowOrder"(flow_order),
arg!"keySequence"(key_sequence));
bases = basesWith!Options(r, arg!"flowOrder"(flow_order),
arg!"keySequence"(key_sequence));
// if reverse strand, bases are also reverse complemented
assert(equal(bases, map!"a.complement"(retro(r.sequence))));
} else {
bases = basesWith!("FZ", "MD")(r, arg!"flowOrder"(flow_order),
arg!"keySequence"(key_sequence));
bases = basesWith!Options(r, arg!"flowOrder"(flow_order),
arg!"keySequence"(key_sequence));
assert(equal(bases, r.sequence));
}
}

Loading…
Cancel
Save