Skip to content

Prototype class for Blended BOQA Exomiser integration - #43

Open
pnrobinson wants to merge 1 commit into
developfrom
blended-exomiser
Open

Prototype class for Blended BOQA Exomiser integration#43
pnrobinson wants to merge 1 commit into
developfrom
blended-exomiser

Conversation

@pnrobinson

Copy link
Copy Markdown
Contributor

@julesjacobsen @hansenp
Prototype architecture for Exomiser integration with BOQA

hansenp added a commit that referenced this pull request Jul 17, 2026
The wrapper currently returns BoqaAnalysisResult, which carries no gene
information and cannot say which diseases a blended entry is made of.
Exomiser needs both to build a PriorityResult: a gene ID and symbol per
result, and the counts of each component next to those of the blend.

Add TargetDisease and BlendedResult, following the prototype design in
PR #43. TargetDisease pairs a candidate disease with the gene that made
it a candidate; the caller supplies gene identity, since it already
knows which gene put the disease on the list, and core would otherwise
have to load gene data it does not need. BlendedResult reports the
components with their genes, each component's counts, the counts the
entry was scored on and its score, with isBlended() distinguishing the
two cases. Single diseases use the same record with one component, so
callers need no second code path.

A blend spans two genes by construction, so both components stay
visible and the caller decides how to map them onto its per-gene
results; the prototype's single finalDisease field is left out, as it
cannot express that.

Neither record refers to Exomiser types, so boqa-core stays free of the
dependency. Nothing constructs them yet; the wrapper switches over in
the next commit.
@hansenp

hansenp commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

@pnrobinson

I have gone through this PR and built its design into #45. The records are the part I was missing: TargetDisease and BlendedResult give Exomiser the gene identity and the per-component counts it needs to build a PriorityResult, without core depending on the Exomiser library. I have taken them over, with small adaptations that I ask about below.

Where I would push back is on the analysis itself. I would like the blended analysis to change exactly one thing: the DiseaseData that goes into the counter. Everything downstream: BoqaSetCounter, BoqaPatientAnalyzer, the scoring, the normalization, should run as it does for the plain analysis. BlendedDiseaseData already implements DiseaseData, so a blend is just another entry and no part of the workflow needs to know that blending exists.

As sketched, this PR goes further. The notes plan to rebuild the counter's index inside the analyser ("private final Map<TermId, Set> diseaseLayers => Create this similar to existing code"), and computeBlendedBoqaResults works out the score itself instead of going through BoqaPatientAnalyzer ("double score = 42.7; // calculate for melded or final"). Filling those in gives us a second copy of what BoqaSetCounter and BoqaPatientAnalyzer already do. The duplication would bother me less than the drift: as soon as the two copies disagree, blended scores are no longer comparable to plain ones.

#45 takes the substitution route. It touches no file of the analysis workflow: not BoqaSetCounter, not BoqaPatientAnalyzer, not AlgorithmParameters, and the 3201 reference-score tests pass unchanged, which is what convinces me that scoring is really untouched. The blended entries are scored by the same code path as everything else.

I think the results already carry what the analyser would otherwise compute. A BlendedResult reports the BoqaCounts of each component next to those of the blend, and the counts determine the raw log score on their own:

log P = fp*log(alpha) + fn*log(beta) + tn*log(1-alpha) + tp*log(1-beta)

Since the caller passes alpha and beta in, it can recompute the raw score of any entry, and a Bayes factor is then the difference of two such scores, a blend against either of its components, for instance. So a Bayes factor threshold does not need to be built into the analysis; it can be applied to the results by whoever wants it, and different callers can use different ones. The one thing missing is access: computeUnnormalizedLogProbability is package-private, so Exomiser would have to restate the formula. If you agree with this route, making it public would be the better answer.

Three things where I would like your opinion:

  1. Which gene does a blended result report? PriorityResult is per gene, but a blend spans two genes by construction. I left your single finalDisease out, and the result carries the full component list with each component's gene, so that the Exomiser side decides how to map it onto per-gene PriorityResults; for a single disease the list has size 1. Does that fit what the BoqaBlendedPrioritiser needs?

  2. Which shared-gene rule belongs here? Your signature takes Set, so Exomiser passes gene identity in and core does no gene lookup, which I have adopted. As a consequence the guard currently compares the two nominating genes and blends whenever they differ. The CLI instead asks whether the two diseases share any gene at all, using the full sets from genes_to_disease.txt. The rules part when two diseases are nominated by different genes but share some third gene: the wrapper blends them, the CLI does not. My instinct is that the CLI's rule is the right one and that the wrapper should use it as well.

  3. Can Exomiser nominate the same disease via two different genes? Nothing in Set prevents it, but BlendedDiseaseData keys its entries by disease ID and cannot hold both, so Boqa blended exomiser integration #45 rejects it for now rather than letting one of the two silently win. If it does happen in practice, we need a rule for it.

One practical note: the #43 branch is based on an older develop (bcbd64d), so it is missing what has landed there since.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants