///|
pub fn AttributePresence::to_string(self : AttributePresence) -> String {
match self {
Required => "required"
Optional => "optional"
Rare => "rare"
}
}
///|
fn schema_presence(count : Int, feature_count : Int) -> AttributePresence {
if feature_count == 0 || count == feature_count {
Required
} else if count * 4 <= feature_count {
Rare
} else {
Optional
}
}
///|
fn schema_has_key(keys : Array[String], key : String) -> Bool {
for item in keys {
if item == key {
return true
}
}
false
}
///|
fn schema_count_key(features : Array[Feature], key : String) -> Int {
let mut count = 0
for feature in features {
for attr in feature.attributes {
if attr.key == key {
count += 1
}
}
}
count
}
///|
fn schema_example_value(features : Array[Feature], key : String) -> String {
for feature in features {
for attr in feature.attributes {
if attr.key == key {
return attr.value
}
}
}
""
}
///|
pub fn Annotation::infer_attribute_schema(self : Annotation) -> AttributeSchema {
let keys : Array[String] = []
let rows : Array[AttributeSchemaRow] = []
for feature in self.features {
for attr in feature.attributes {
if !schema_has_key(keys, attr.key) {
keys.push(attr.key)
let count = schema_count_key(self.features, attr.key)
rows.push({
key: attr.key,
count,
feature_count: self.features.length(),
presence: schema_presence(count, self.features.length()),
example_value: schema_example_value(self.features, attr.key),
})
}
}
}
{ rows, }
}
///|
pub fn AttributeSchema::required_keys(self : AttributeSchema) -> Array[String] {
let keys : Array[String] = []
for row in self.rows {
if row.presence == Required {
keys.push(row.key)
}
}
keys
}
///|
pub fn AttributeSchema::optional_keys(self : AttributeSchema) -> Array[String] {
let keys : Array[String] = []
for row in self.rows {
if row.presence == Optional {
keys.push(row.key)
}
}
keys
}
///|
pub fn AttributeSchema::rare_keys(self : AttributeSchema) -> Array[String] {
let keys : Array[String] = []
for row in self.rows {
if row.presence == Rare {
keys.push(row.key)
}
}
keys
}
///|
pub fn AttributeSchema::to_tsv(self : AttributeSchema) -> String {
let lines : Array[String] = [
"attribute\tcount\tfeature_count\tpresence\texample",
]
for row in self.rows {
lines.push(
[
row.key,
"\{row.count}",
"\{row.feature_count}",
row.presence.to_string(),
row.example_value,
].join("\t"),
)
}
lines.join("\n") + "\n"
}