///|
fn contains_seqid(seqids : Array[String], seqid : String) -> Bool {
for item in seqids {
if item == seqid {
return true
}
}
false
}
///|
fn summarize_seqid(
features : Array[Feature],
seqid : String,
) -> SequenceSummary {
let mut feature_count = 0
let mut min_start = 0
let mut max_end = 0
let mut plus = 0
let mut minus = 0
let mut unknown = 0
for feature in features {
if feature.seqid == seqid {
if feature_count == 0 {
min_start = feature.start
max_end = feature.end
} else {
if feature.start < min_start {
min_start = feature.start
}
if feature.end > max_end {
max_end = feature.end
}
}
feature_count += 1
match feature.strand {
Plus => plus += 1
Minus => minus += 1
_ => unknown += 1
}
}
}
{
seqid,
feature_count,
min_start,
max_end,
strand_plus_count: plus,
strand_minus_count: minus,
strand_unknown_count: unknown,
}
}
///|
pub fn Annotation::sequence_summaries(
self : Annotation,
) -> Array[SequenceSummary] {
let seqids : Array[String] = []
let rows : Array[SequenceSummary] = []
for feature in self.features {
if !contains_seqid(seqids, feature.seqid) {
seqids.push(feature.seqid)
rows.push(summarize_seqid(self.features, feature.seqid))
}
}
rows
}
///|
pub fn SequenceSummary::span_bases(self : SequenceSummary) -> Int {
if self.feature_count == 0 {
0
} else {
self.max_end - self.min_start + 1
}
}
///|
pub fn SequenceSummary::to_tsv_row(self : SequenceSummary) -> String {
[
self.seqid,
"\{self.feature_count}",
"\{self.min_start}",
"\{self.max_end}",
"\{self.span_bases()}",
"\{self.strand_plus_count}",
"\{self.strand_minus_count}",
"\{self.strand_unknown_count}",
].join("\t")
}
///|
pub fn Annotation::sequence_summary_tsv(self : Annotation) -> String {
let lines : Array[String] = [
"seqid\tfeature_count\tmin_start\tmax_end\tspan_bases\tplus\tminus\tunknown",
]
for row in self.sequence_summaries() {
lines.push(row.to_tsv_row())
}
lines.join("\n") + "\n"
}