Prototype class for Blended BOQA Exomiser integration - #43
Conversation
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.
|
I have gone through this PR and built its design into #45. The records are the part I was missing: 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: 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:
One practical note: the #43 branch is based on an older develop (bcbd64d), so it is missing what has landed there since. |
@julesjacobsen @hansenp
Prototype architecture for Exomiser integration with BOQA