Class CommonalityRankingStrategy

java.lang.Object
ubic.gemma.rest.ranking.CommonalityRankingStrategy
All Implemented Interfaces:
AnnotationSearchRankingStrategy

@Component("commonality") public class CommonalityRankingStrategy extends Object implements AnnotationSearchRankingStrategy
Orders hits by how commonly prior curators wrote the query string to mean each candidate.

This asks a different question from UsageWeightedRankingStrategy. A usage count is about the TERM — how much does Gemma use this URI at all — and answers "which compound is meant". The per-string prior is about the STRING: of everyone who actually wrote the words being searched for, how many meant each candidate. On the production corpus a search for dmso finds that 508 experiments writing "DMSO" meant the compound and 16 meant reference substance role, which separates them even though both are legitimate hits and both terms are well used in their own right.

Score: rankWeight * (1 / (1 + originalRank)) + priorWeight * priorScore(prior, maxPrior) - shapeWeight * designationPenalty(label). Higher sorts earlier; ties resolve by original Lucene rank ascending, so the strategy is stable and never reorders hits it cannot separate. The prior is scored relative to the strongest candidate in the same result set — see priorScore(int, int) for why an absolute scale cannot work here.

Two constraints the measurement imposed

  1. It is a frequency comparison, not a preference for synonyms. The tempting shortcut — prefer whichever string is a synonym rather than the preferred label — is wrong: DMSO (508) beats the label dimethyl sulfoxide, but EtOH (38) LOSES to the label ethanol (65). Only the counts can tell those apart, so only the counts are consulted.
  2. A compound nobody has curated scores zero everywhere. Corpus frequency is silent on a drug the corpus has never seen — the case that matters most when annotating something for the first time. Rather than let a zero-information tie fall through to URI string order, designationPenalty(String) demotes labels shaped like systematic chemical names, which nobody writes when they mean the drug.

Purely numeric query strings never reach here with a populated prior: a count of 24 pools unrelated doses, timepoints and replicate numbers, so the tally is refused at the DAO.

The prior is corpus curation history, so it reflects whatever is in the database, escrowed experiments included. That is the same footing as ?rank=usage and fine for ordering a live search; it is NOT a held-out signal and must not be treated as one when measuring a resolver against an escrow.