///|
pub fn corpus_profile(
qrels : Array[JudgedDoc],
run : Array[RetrievedDoc],
) -> CorpusProfile {
let qrels_by_query = group_qrels(qrels)
let runs_by_query = group_runs(run)
let query_ids = sorted_query_ids(qrels_by_query, runs_by_query)
let relevance = build_relevance_map(qrels)
let mut relevant = 0
let mut maximum = 0
for _, value in relevance {
maximum = Int::max(maximum, value)
if value > 0 {
relevant += 1
}
}
let mut unjudged = 0
for item in run {
if !relevance.contains(item.doc_id) {
unjudged += 1
}
}
let unique_docs : Map[String, Unit] = Map([])
for item in qrels {
unique_docs[item.doc_id] = ()
}
for item in run {
unique_docs[item.doc_id] = ()
}
let mut judgment_total = 0
for _, items in qrels_by_query {
judgment_total += items.length()
}
{
query_count: query_ids.length(),
qrels_rows: qrels.length(),
run_rows: run.length(),
unique_document_count: unique_docs.length(),
relevant_document_count: relevant,
max_relevance: maximum,
unjudged_retrievals: unjudged,
mean_judgments_per_query: if query_ids.is_empty() {
0.0
} else {
Double::from_int(judgment_total) / Double::from_int(query_ids.length())
},
mean_run_length: if query_ids.is_empty() {
0.0
} else {
Double::from_int(run.length()) / Double::from_int(query_ids.length())
},
mean_score: score_mean(run),
score_stddev: score_stddev(run),
}
}
///|
pub fn relevance_histogram(qrels : Array[JudgedDoc]) -> Map[Int, Int] {
let histogram : Map[Int, Int] = Map([])
for item in qrels {
histogram[item.relevance] = histogram.get_or_default(item.relevance, 0) + 1
}
histogram
}
///|
pub fn render_corpus_profile(profile : CorpusProfile) -> String {
let lines : Array[String] = [
"Corpus profile",
"queries=\{profile.query_count}",
"qrels_rows=\{profile.qrels_rows}",
"run_rows=\{profile.run_rows}",
"unique_documents=\{profile.unique_document_count}",
"relevant_documents=\{profile.relevant_document_count}",
"max_relevance=\{profile.max_relevance}",
"unjudged_retrievals=\{profile.unjudged_retrievals}",
"mean_judgments_per_query=\{format_metric(profile.mean_judgments_per_query)}",
"mean_run_length=\{format_metric(profile.mean_run_length)}",
"mean_score=\{format_metric(profile.mean_score)}",
"score_stddev=\{format_metric(profile.score_stddev)}",
]
lines.join("\n")
}
///|
pub fn corpus_profile_json(profile : CorpusProfile) -> String {
ToJson::to_json(profile).stringify(indent=2)
}
///|
pub fn document_relevance_levels(qrels : Array[JudgedDoc]) -> Array[Int] {
let levels : Map[Int, Unit] = Map([])
for item in qrels {
levels[item.relevance] = ()
}
let result : Array[Int] = []
for level, _ in levels {
result.push(level)
}
result.sort()
result
}