2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
package gui
|
|
|
|
|
|
|
|
// viewAnalysisGui_Person.go implements pages to view a person genetic analysis
|
|
|
|
|
|
|
|
//TODO: Use person's sex to show opposite sex diseases and traits in different section
|
|
|
|
// For example, Ovarian Cancer for men, and Testicular Cancer for women
|
|
|
|
// We still want these risks/traits to be viewable, just put into a different part of the gui
|
|
|
|
|
|
|
|
import "fyne.io/fyne/v2"
|
|
|
|
import "fyne.io/fyne/v2/container"
|
|
|
|
import "fyne.io/fyne/v2/layout"
|
|
|
|
import "fyne.io/fyne/v2/theme"
|
|
|
|
import "fyne.io/fyne/v2/widget"
|
|
|
|
|
2024-08-15 14:14:23 +02:00
|
|
|
import "seekia/resources/trainedPredictionModels"
|
2024-04-11 15:51:56 +02:00
|
|
|
import "seekia/resources/geneticReferences/monogenicDiseases"
|
|
|
|
import "seekia/resources/geneticReferences/polygenicDiseases"
|
|
|
|
import "seekia/resources/geneticReferences/traits"
|
|
|
|
|
|
|
|
import "seekia/internal/appMemory"
|
2024-06-02 10:43:39 +02:00
|
|
|
import "seekia/internal/encoding"
|
|
|
|
import "seekia/internal/genetics/geneticAnalysis"
|
2024-04-11 15:51:56 +02:00
|
|
|
import "seekia/internal/genetics/myGenomes"
|
|
|
|
import "seekia/internal/genetics/myPeople"
|
|
|
|
import "seekia/internal/genetics/readGeneticAnalysis"
|
|
|
|
import "seekia/internal/helpers"
|
|
|
|
|
2024-08-09 16:23:37 +02:00
|
|
|
import "slices"
|
2024-04-11 15:51:56 +02:00
|
|
|
import "errors"
|
|
|
|
|
2024-08-09 16:23:37 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
func setViewPersonGeneticAnalysisPage(window fyne.Window, personIdentifier string, analysisObject geneticAnalysis.PersonAnalysis, numberOfGenomesAnalyzed int, previousPage func()){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
appMemory.SetMemoryEntry("CurrentViewedPage", "ViewGeneticAnalysisPage")
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
currentPage := func(){setViewPersonGeneticAnalysisPage(window, personIdentifier, analysisObject, numberOfGenomesAnalyzed, previousPage)}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
title := getPageTitleCentered("Viewing Genetic Analysis")
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
warningLabel1 := getBoldLabelCentered("WARNING: Results are not accurate!")
|
|
|
|
warningLabel2 := getBoldLabelCentered("The analysis algorithms have known issues that are being worked on.")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
personFound, personName, _, _, err := myPeople.GetPersonInfo(personIdentifier)
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (personFound == false){
|
|
|
|
setErrorEncounteredPage(window, errors.New("setViewPersonGeneticAnalysisPage called with unknown personIdentifier: " + personIdentifier), previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
personNameLabel := widget.NewLabel("Person Name:")
|
|
|
|
personNameText := getBoldLabel(personName)
|
|
|
|
personNameRow := container.NewHBox(layout.NewSpacer(), personNameLabel, personNameText, layout.NewSpacer())
|
|
|
|
|
|
|
|
numberOfGenomesAnalyzedString := helpers.ConvertIntToString(numberOfGenomesAnalyzed)
|
|
|
|
|
|
|
|
numberOfAnalyzedGenomesLabel := widget.NewLabel("Number of Analyzed Genomes:")
|
|
|
|
numberOfAnalyzedGenomesText := getBoldLabel(numberOfGenomesAnalyzedString)
|
|
|
|
numberOfAnalyzedGenomesRow := container.NewHBox(layout.NewSpacer(), numberOfAnalyzedGenomesLabel, numberOfAnalyzedGenomesText, layout.NewSpacer())
|
|
|
|
|
|
|
|
generalButton := widget.NewButton("General", func(){
|
|
|
|
//TODO: Inbred rating (parent relatedness), ancestry
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
})
|
|
|
|
monogenicDiseasesButton := widget.NewButton("Monogenic Diseases", func(){
|
2024-06-02 10:43:39 +02:00
|
|
|
setViewPersonGeneticAnalysisMonogenicDiseasesPage(window, analysisObject, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
polygenicDiseasesButton := widget.NewButton("Polygenic Diseases", func(){
|
2024-06-02 10:43:39 +02:00
|
|
|
setViewPersonGeneticAnalysisPolygenicDiseasesPage(window, personIdentifier, analysisObject, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
2024-07-19 19:16:28 +02:00
|
|
|
discreteTraitsButton := widget.NewButton("Discrete Traits", func(){
|
|
|
|
setViewPersonGeneticAnalysisDiscreteTraitsPage(window, personIdentifier, analysisObject, currentPage)
|
|
|
|
})
|
|
|
|
numericTraitsButton := widget.NewButton("Numeric Traits", func(){
|
2024-08-09 16:23:37 +02:00
|
|
|
setViewPersonGeneticAnalysisNumericTraitsPage(window, personIdentifier, analysisObject, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
categoryButtonsGrid := getContainerCentered(container.NewGridWithColumns(1, generalButton, monogenicDiseasesButton, polygenicDiseasesButton, discreteTraitsButton, numericTraitsButton))
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), warningLabel1, warningLabel2, widget.NewSeparator(), personNameRow, numberOfAnalyzedGenomesRow, widget.NewSeparator(), categoryButtonsGrid)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
func setViewPersonGeneticAnalysisMonogenicDiseasesPage(window fyne.Window, analysisObject geneticAnalysis.PersonAnalysis, previousPage func()){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
currentPage := func(){setViewPersonGeneticAnalysisMonogenicDiseasesPage(window, analysisObject, previousPage)}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
title := getPageTitleCentered("Viewing Genetic Analysis - Monogenic Diseases")
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
|
|
|
|
description := getLabelCentered("Below is an analysis of the monogenic diseases found in the person's genome.")
|
|
|
|
|
|
|
|
getMonogenicDiseasesContainer := func()(*fyne.Container, error){
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, _, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(analysisObject)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
// Outputs:
|
2024-06-02 10:43:39 +02:00
|
|
|
// -[16]byte: Main genome identifier (Is either the combined Only exclude conflicts genome or the only genome)
|
2024-04-11 15:51:56 +02:00
|
|
|
// -error
|
2024-06-02 10:43:39 +02:00
|
|
|
getMainGenomeIdentifier := func()([16]byte, error){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
return onlyExcludeConflictsGenomeIdentifier, nil
|
|
|
|
}
|
|
|
|
// Only 1 genome exists
|
|
|
|
|
|
|
|
genomeIdentifier := allRawGenomeIdentifiersList[0]
|
|
|
|
|
|
|
|
return genomeIdentifier, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
mainGenomeIdentifier, err := getMainGenomeIdentifier()
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
diseaseNameLabel := getItalicLabelCentered("Disease Name")
|
|
|
|
emptyLabelA := widget.NewLabel("")
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
personLabel := getItalicLabelCentered("Person")
|
|
|
|
hasDiseaseLabel := getItalicLabelCentered("Has Disease")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
probabilityOfLabel := getItalicLabelCentered("Probability of")
|
2024-04-11 15:51:56 +02:00
|
|
|
passingVariantLabel := getItalicLabelCentered("Passing Variant")
|
|
|
|
|
|
|
|
emptyLabelB := widget.NewLabel("")
|
|
|
|
conflictExistsLabel := getItalicLabelCentered("Conflict Exists?")
|
|
|
|
|
|
|
|
emptyLabelC := widget.NewLabel("")
|
|
|
|
emptyLabelD := widget.NewLabel("")
|
|
|
|
|
|
|
|
diseaseNameColumn := container.NewVBox(emptyLabelA, diseaseNameLabel, widget.NewSeparator())
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseColumn := container.NewVBox(personLabel, hasDiseaseLabel, widget.NewSeparator())
|
|
|
|
probabilityOfPassingVariantColumn := container.NewVBox(probabilityOfLabel, passingVariantLabel, widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
conflictExistsColumn := container.NewVBox(emptyLabelB, conflictExistsLabel, widget.NewSeparator())
|
|
|
|
viewButtonsColumn := container.NewVBox(emptyLabelC, emptyLabelD, widget.NewSeparator())
|
|
|
|
|
|
|
|
monogenicDiseaseNamesList, err := monogenicDiseases.GetMonogenicDiseaseNamesList()
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
for _, diseaseName := range monogenicDiseaseNamesList{
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
diseaseInfoIsKnown, personHasDisease, _, probabilityOfPassingAVariantFormatted, _, _, _, conflictExistsBool, err := readGeneticAnalysis.GetPersonMonogenicDiseaseInfoFromGeneticAnalysis(analysisObject, diseaseName, mainGenomeIdentifier)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
getPersonHasDiseaseText := func()string{
|
|
|
|
if (diseaseInfoIsKnown == false){
|
2024-04-11 15:51:56 +02:00
|
|
|
result := translate("Unknown")
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseString := helpers.ConvertBoolToYesOrNoString(personHasDisease)
|
|
|
|
|
|
|
|
return personHasDiseaseString
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseText := getPersonHasDiseaseText()
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
getProbabilityOfPassingAVariantText := func()string{
|
2024-06-02 10:43:39 +02:00
|
|
|
if (diseaseInfoIsKnown == false){
|
2024-04-11 15:51:56 +02:00
|
|
|
result := translate("Unknown")
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
return probabilityOfPassingAVariantFormatted
|
|
|
|
}
|
|
|
|
|
|
|
|
probabilityOfPassingAVariantText := getProbabilityOfPassingAVariantText()
|
|
|
|
|
|
|
|
diseaseNameText := getBoldLabelCentered(diseaseName)
|
|
|
|
diseaseNameColumn.Add(diseaseNameText)
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseLabel := getBoldLabelCentered(personHasDiseaseText)
|
|
|
|
personHasDiseaseColumn.Add(personHasDiseaseLabel)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
probabilityOfPassingVariantLabel := getBoldLabelCentered(probabilityOfPassingAVariantText)
|
|
|
|
probabilityOfPassingVariantColumn.Add(probabilityOfPassingVariantLabel)
|
|
|
|
|
|
|
|
conflictExistsString := helpers.ConvertBoolToYesOrNoString(conflictExistsBool)
|
|
|
|
conflictExistsLabel := getBoldLabelCentered(conflictExistsString)
|
|
|
|
conflictExistsColumn.Add(conflictExistsLabel)
|
|
|
|
|
|
|
|
viewDetailsButton := getWidgetCentered(widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
|
2024-06-02 10:43:39 +02:00
|
|
|
setViewPersonGeneticAnalysisMonogenicDiseaseDetailsPage(window, analysisObject, diseaseName, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
}))
|
|
|
|
viewButtonsColumn.Add(viewDetailsButton)
|
|
|
|
|
|
|
|
diseaseNameColumn.Add(widget.NewSeparator())
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseColumn.Add(widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
probabilityOfPassingVariantColumn.Add(widget.NewSeparator())
|
|
|
|
conflictExistsColumn.Add(widget.NewSeparator())
|
|
|
|
viewButtonsColumn.Add(widget.NewSeparator())
|
|
|
|
}
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setPersonHasMonogenicDiseaseExplainerPage(window, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseColumn.Add(personHasDiseaseHelpButton)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
probabilityOfPassingVariantHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setPersonProbabilityOfPassingVariantExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
probabilityOfPassingVariantColumn.Add(probabilityOfPassingVariantHelpButton)
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
diseasesContainer := container.NewHBox(layout.NewSpacer(), diseaseNameColumn, personHasDiseaseColumn, probabilityOfPassingVariantColumn)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
|
|
|
|
conflictExistsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setPersonGeneticAnalysisConflictExistsExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
|
|
|
|
conflictExistsColumn.Add(conflictExistsHelpButton)
|
|
|
|
diseasesContainer.Add(conflictExistsColumn)
|
|
|
|
}
|
|
|
|
|
|
|
|
diseasesContainer.Add(viewButtonsColumn)
|
|
|
|
diseasesContainer.Add(layout.NewSpacer())
|
|
|
|
|
|
|
|
return diseasesContainer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
monogenicDiseasesContainer, err := getMonogenicDiseasesContainer()
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), monogenicDiseasesContainer)
|
|
|
|
|
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
func setViewPersonGeneticAnalysisMonogenicDiseaseDetailsPage(window fyne.Window, analysisObject geneticAnalysis.PersonAnalysis, diseaseName string, previousPage func()){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
currentPage := func(){setViewPersonGeneticAnalysisMonogenicDiseaseDetailsPage(window, analysisObject, diseaseName, previousPage)}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
title := getPageTitleCentered("Viewing Genetic Analysis - " + diseaseName)
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
2024-07-19 19:16:28 +02:00
|
|
|
|
|
|
|
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, onlyIncludeSharedGenomeIdentifier, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(analysisObject)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) {
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
getDescriptionSection := func()*fyne.Container{
|
|
|
|
|
|
|
|
if (multipleGenomesExist == false){
|
|
|
|
description := getLabelCentered("Below is the disease information for this person's genome.")
|
|
|
|
|
|
|
|
return description
|
|
|
|
}
|
|
|
|
|
|
|
|
description1 := getLabelCentered("Below is the disease information for this person's genomes.")
|
|
|
|
description2 := getLabelCentered("The first two genomes are created by combining multiple genomes.")
|
|
|
|
|
|
|
|
descriptionsSection := container.NewVBox(description1, description2)
|
|
|
|
|
|
|
|
return descriptionsSection
|
|
|
|
}
|
|
|
|
|
|
|
|
descriptionSection := getDescriptionSection()
|
|
|
|
|
|
|
|
diseaseNameLabel := widget.NewLabel("Disease:")
|
|
|
|
diseaseNameText := getBoldLabel(diseaseName)
|
|
|
|
diseaseNameInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){
|
|
|
|
setViewMonogenicDiseaseDetailsPage(window, diseaseName, currentPage)
|
|
|
|
})
|
|
|
|
diseaseNameRow := container.NewHBox(layout.NewSpacer(), diseaseNameLabel, diseaseNameText, diseaseNameInfoButton, layout.NewSpacer())
|
|
|
|
|
|
|
|
getGenomesContainer := func()(*fyne.Container, error){
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
diseaseVariantsMap, err := monogenicDiseases.GetMonogenicDiseaseVariantsMap(diseaseName)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
totalNumberOfVariants := len(diseaseVariantsMap)
|
|
|
|
totalNumberOfVariantsString := helpers.ConvertIntToString(totalNumberOfVariants)
|
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
emptyLabelA := widget.NewLabel("")
|
2024-06-02 10:43:39 +02:00
|
|
|
genomeNameLabel := getItalicLabelCentered("Genome Name")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
personLabel := getItalicLabelCentered("Person")
|
|
|
|
hasDiseaseLabel := getItalicLabelCentered("Has Disease")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
probabilityOfLabel := getItalicLabelCentered("Probability of")
|
2024-04-11 15:51:56 +02:00
|
|
|
passingVariantLabel := getItalicLabelCentered("Passing Variant")
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
numberOfLabel1 := getItalicLabelCentered("Number of")
|
2024-04-11 15:51:56 +02:00
|
|
|
variantsTestedLabel := getItalicLabelCentered("Variants Tested")
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
numberOfLabel2 := getItalicLabelCentered("Number of")
|
|
|
|
phasedLociLabel := getItalicLabelCentered("Phased Loci")
|
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
emptyLabelB := widget.NewLabel("")
|
|
|
|
emptyLabelC := widget.NewLabel("")
|
|
|
|
|
|
|
|
genomeNameColumn := container.NewVBox(emptyLabelA, genomeNameLabel, widget.NewSeparator())
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseColumn := container.NewVBox(personLabel, hasDiseaseLabel, widget.NewSeparator())
|
|
|
|
probabilityOfPassingAVariantColumn := container.NewVBox(probabilityOfLabel, passingVariantLabel, widget.NewSeparator())
|
|
|
|
numberOfVariantsTestedColumn := container.NewVBox(numberOfLabel1, variantsTestedLabel, widget.NewSeparator())
|
|
|
|
numberOfPhasedLociColumn := container.NewVBox(numberOfLabel2, phasedLociLabel, widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
viewButtonsColumn := container.NewVBox(emptyLabelB, emptyLabelC, widget.NewSeparator())
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
addGenomeRow := func(genomeName string, genomeIdentifier [16]byte, isACombinedGenome bool)error{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
diseaseInfoIsKnown, personHasDisease, _, probabilityOfPassingAVariantFormatted, numberOfVariantsTested, numberOfLociTested, numberOfPhasedLoci, _, err := readGeneticAnalysis.GetPersonMonogenicDiseaseInfoFromGeneticAnalysis(analysisObject, diseaseName, genomeIdentifier)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return err }
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
getPersonHasDiseaseText := func()string{
|
|
|
|
if (diseaseInfoIsKnown == false){
|
2024-04-11 15:51:56 +02:00
|
|
|
result := translate("Unknown")
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseString := helpers.ConvertBoolToYesOrNoString(personHasDisease)
|
|
|
|
|
|
|
|
return personHasDiseaseString
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseText := getPersonHasDiseaseText()
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
getProbabilityOfPassingAVariantText := func()string{
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
if (diseaseInfoIsKnown == false){
|
2024-04-11 15:51:56 +02:00
|
|
|
result := translate("Unknown")
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
return probabilityOfPassingAVariantFormatted
|
|
|
|
}
|
|
|
|
|
|
|
|
probabilityOfPassingAVariantText := getProbabilityOfPassingAVariantText()
|
|
|
|
|
|
|
|
getGenomeNameCell := func()*fyne.Container{
|
|
|
|
if (isACombinedGenome == false){
|
|
|
|
|
|
|
|
genomeNameLabel := getBoldLabelCentered(genomeName)
|
|
|
|
return genomeNameLabel
|
|
|
|
}
|
|
|
|
viewHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setCombinedGenomesExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
|
|
|
|
genomeNameLabel := getBoldLabel(genomeName)
|
|
|
|
genomeNameCell := container.NewHBox(layout.NewSpacer(), viewHelpButton, genomeNameLabel, layout.NewSpacer())
|
|
|
|
|
|
|
|
return genomeNameCell
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeNameCell := getGenomeNameCell()
|
|
|
|
genomeNameColumn.Add(genomeNameCell)
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseLabel := getBoldLabelCentered(personHasDiseaseText)
|
|
|
|
personHasDiseaseColumn.Add(personHasDiseaseLabel)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
probabilityOfPassingAVariantLabel := getBoldLabelCentered(probabilityOfPassingAVariantText)
|
|
|
|
probabilityOfPassingAVariantColumn.Add(probabilityOfPassingAVariantLabel)
|
|
|
|
|
|
|
|
numberOfVariantsTestedString := helpers.ConvertIntToString(numberOfVariantsTested)
|
2024-06-02 10:43:39 +02:00
|
|
|
numberOfVariantsTestedFormatted := numberOfVariantsTestedString + "/" + totalNumberOfVariantsString
|
|
|
|
numberOfVariantsTestedLabel := getBoldLabelCentered(numberOfVariantsTestedFormatted)
|
2024-04-11 15:51:56 +02:00
|
|
|
numberOfVariantsTestedColumn.Add(numberOfVariantsTestedLabel)
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
numberOfLociTestedString := helpers.ConvertIntToString(numberOfLociTested)
|
|
|
|
numberOfPhasedLociString := helpers.ConvertIntToString(numberOfPhasedLoci)
|
|
|
|
numberOfPhasedLociFormatted := numberOfPhasedLociString + "/" + numberOfLociTestedString
|
|
|
|
numberOfPhasedLociLabel := getBoldLabelCentered(numberOfPhasedLociFormatted)
|
|
|
|
numberOfPhasedLociColumn.Add(numberOfPhasedLociLabel)
|
|
|
|
|
|
|
|
viewButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
|
|
|
|
setViewPersonGenomeMonogenicDiseaseVariantsPage(window, analysisObject, genomeIdentifier, genomeName, diseaseName, currentPage)
|
|
|
|
})
|
2024-04-11 15:51:56 +02:00
|
|
|
viewButtonsColumn.Add(viewButton)
|
|
|
|
|
|
|
|
genomeNameColumn.Add(widget.NewSeparator())
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseColumn.Add(widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
probabilityOfPassingAVariantColumn.Add(widget.NewSeparator())
|
|
|
|
numberOfVariantsTestedColumn.Add(widget.NewSeparator())
|
2024-06-02 10:43:39 +02:00
|
|
|
numberOfPhasedLociColumn.Add(widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
viewButtonsColumn.Add(widget.NewSeparator())
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
|
|
|
|
err := addGenomeRow("Only Exclude Conflicts", onlyExcludeConflictsGenomeIdentifier, true)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
err = addGenomeRow("Only Include Shared", onlyIncludeSharedGenomeIdentifier, true)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, genomeIdentifier := range allRawGenomeIdentifiersList{
|
|
|
|
|
|
|
|
getGenomeName := func()(string, error){
|
|
|
|
|
|
|
|
genomeFound, _, timeGenomeWasExported, _, _, _, companyName, _, _, err := myGenomes.GetMyRawGenomeMetadata(genomeIdentifier)
|
|
|
|
if (err != nil) { return "", err }
|
|
|
|
if (genomeFound == false){
|
2024-06-02 10:43:39 +02:00
|
|
|
return "", errors.New("MyGenomeInfo for genome from analysisObject not found.")
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (multipleGenomesExist == false){
|
|
|
|
return companyName, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// We show the date that the genome was exported
|
|
|
|
|
|
|
|
exportTimeAgo, err := helpers.ConvertUnixTimeToTimeAgoTranslated(timeGenomeWasExported, false)
|
|
|
|
if (err != nil){ return "", err }
|
|
|
|
|
|
|
|
genomeName := companyName + " (Exported " + exportTimeAgo + ")"
|
|
|
|
|
|
|
|
return genomeName, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeName, err := getGenomeName()
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
err = addGenomeRow(genomeName, genomeIdentifier, false)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
}
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setPersonHasMonogenicDiseaseExplainerPage(window, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
2024-06-02 10:43:39 +02:00
|
|
|
personHasDiseaseColumn.Add(personHasDiseaseHelpButton)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
probabilityOfPassingAVariantHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setPersonProbabilityOfPassingVariantExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
probabilityOfPassingAVariantColumn.Add(probabilityOfPassingAVariantHelpButton)
|
|
|
|
|
|
|
|
numberOfVariantsTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setNumberOfTestedVariantsExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
numberOfVariantsTestedColumn.Add(numberOfVariantsTestedHelpButton)
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
numberOfPhasedLociHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setNumberOfPhasedLociExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
numberOfPhasedLociColumn.Add(numberOfPhasedLociHelpButton)
|
|
|
|
|
|
|
|
genomesContainer := container.NewHBox(layout.NewSpacer(), genomeNameColumn, personHasDiseaseColumn, probabilityOfPassingAVariantColumn, numberOfVariantsTestedColumn, numberOfPhasedLociColumn, viewButtonsColumn, layout.NewSpacer())
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
return genomesContainer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genomesContainer, err := getGenomesContainer()
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), descriptionSection, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), genomesContainer)
|
2024-06-02 10:43:39 +02:00
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This page is used to view the person's variants for a particular genome
|
2024-06-02 10:43:39 +02:00
|
|
|
func setViewPersonGenomeMonogenicDiseaseVariantsPage(window fyne.Window, geneticAnalysisObject geneticAnalysis.PersonAnalysis, genomeIdentifier [16]byte, genomeName string, diseaseName string, previousPage func()){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
setLoadingScreen(window, "Loading Disease Variants", "Loading disease variants...")
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
currentPage := func(){setViewPersonGenomeMonogenicDiseaseVariantsPage(window, geneticAnalysisObject, genomeIdentifier, genomeName, diseaseName, previousPage)}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
title := getPageTitleCentered("View Monogenic Disease Variants - " + diseaseName)
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
|
|
|
|
description1 := widget.NewLabel("Below are the monogenic disease variant results for this genome.")
|
|
|
|
variantsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setMonogenicDiseaseVariantsExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
description1Row := container.NewHBox(layout.NewSpacer(), description1, variantsHelpButton, layout.NewSpacer())
|
|
|
|
|
|
|
|
getGenomeNameRow := func()*fyne.Container{
|
|
|
|
|
|
|
|
genomeLabel := widget.NewLabel("Genome:")
|
|
|
|
genomeNameLabel := getBoldLabel(genomeName)
|
|
|
|
|
|
|
|
if (genomeName == "Only Exclude Conflicts" || genomeName == "Only Include Shared"){
|
|
|
|
genomeHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setCombinedGenomesExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
genomeNameRow := container.NewHBox(layout.NewSpacer(), genomeLabel, genomeNameLabel, genomeHelpButton, layout.NewSpacer())
|
|
|
|
return genomeNameRow
|
|
|
|
}
|
|
|
|
genomeNameRow := container.NewHBox(layout.NewSpacer(), genomeLabel, genomeNameLabel, layout.NewSpacer())
|
|
|
|
return genomeNameRow
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeNameRow := getGenomeNameRow()
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
_, _, _, _, numberOfVariantsTested, numberOfLociTested, numberOfPhasedLoci, _, err := readGeneticAnalysis.GetPersonMonogenicDiseaseInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, genomeIdentifier)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) {
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
diseaseVariantsMap, err := monogenicDiseases.GetMonogenicDiseaseVariantsMap(diseaseName)
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
totalNumberOfVariants := len(diseaseVariantsMap)
|
|
|
|
totalNumberOfVariantsString := helpers.ConvertIntToString(totalNumberOfVariants)
|
|
|
|
|
|
|
|
numberOfVariantsTestedString := helpers.ConvertIntToString(numberOfVariantsTested)
|
|
|
|
|
|
|
|
variantsTestedLabel := widget.NewLabel("Variants Tested:")
|
|
|
|
variantsTestedText := getBoldLabel(numberOfVariantsTestedString + "/" + totalNumberOfVariantsString)
|
|
|
|
variantsTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setNumberOfTestedVariantsExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
|
|
|
|
variantsTestedRow := container.NewHBox(layout.NewSpacer(), variantsTestedLabel, variantsTestedText, variantsTestedHelpButton, layout.NewSpacer())
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
numberOfLociTestedString := helpers.ConvertIntToString(numberOfLociTested)
|
|
|
|
numberOfPhasedLociString := helpers.ConvertIntToString(numberOfPhasedLoci)
|
|
|
|
|
|
|
|
phasedLociLabel := widget.NewLabel("Phased Loci:")
|
|
|
|
phasedLociText := getBoldLabel(numberOfPhasedLociString + "/" + numberOfLociTestedString)
|
|
|
|
phasedLociHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setNumberOfPhasedLociExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
phasedLociRow := container.NewHBox(layout.NewSpacer(), phasedLociLabel, phasedLociText, phasedLociHelpButton, layout.NewSpacer())
|
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
//TODO: Add navigation buttons and pages
|
|
|
|
|
|
|
|
getVariantsGrid := func()(*fyne.Container, error){
|
|
|
|
|
|
|
|
variantNameLabel := getItalicLabelCentered("Variant Name")
|
|
|
|
genomeHasMutationLabel := getItalicLabelCentered("Genome Has Mutation")
|
|
|
|
numberOfMutationsLabel := getItalicLabelCentered("Number of Mutations")
|
|
|
|
emptyLabel := widget.NewLabel("")
|
|
|
|
|
|
|
|
variantNameColumn := container.NewVBox(variantNameLabel, widget.NewSeparator())
|
|
|
|
genomeHasMutationColumn := container.NewVBox(genomeHasMutationLabel, widget.NewSeparator())
|
|
|
|
numberOfMutationsColumn := container.NewVBox(numberOfMutationsLabel, widget.NewSeparator())
|
|
|
|
viewButtonsColumn := container.NewVBox(emptyLabel, widget.NewSeparator())
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
addVariantRow := func(variantIdentifierHex string)error{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
variantObject, exists := diseaseVariantsMap[variantIdentifierHex]
|
2024-04-11 15:51:56 +02:00
|
|
|
if (exists == false) {
|
|
|
|
return errors.New("Cannot add variantRow: diseaseVariantsMap missing variant.")
|
|
|
|
}
|
|
|
|
|
|
|
|
variantName := variantObject.VariantNames[0]
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
variantIdentifier, err := encoding.DecodeHexStringTo3ByteArray(variantIdentifierHex)
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
numberOfMutationsIsKnown, genomeNumberOfMutations, err := readGeneticAnalysis.GetPersonMonogenicDiseaseVariantInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, variantIdentifier, genomeIdentifier)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
variantNameLabel := getBoldLabelCentered(variantName)
|
|
|
|
variantNameColumn.Add(variantNameLabel)
|
|
|
|
|
|
|
|
getGenomeHasMutationString := func()string{
|
|
|
|
if (numberOfMutationsIsKnown == false){
|
|
|
|
result := translate("Unknown")
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
if (genomeNumberOfMutations == 0){
|
|
|
|
result := translate("No")
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
result := translate("Yes")
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeHasMutationString := getGenomeHasMutationString()
|
|
|
|
|
|
|
|
genomeHasMutationLabel := getBoldLabelCentered(genomeHasMutationString)
|
|
|
|
genomeHasMutationColumn.Add(genomeHasMutationLabel)
|
|
|
|
|
|
|
|
getNumberOfVariantMutationsString := func()string{
|
|
|
|
|
|
|
|
if (numberOfMutationsIsKnown == false){
|
|
|
|
result := translate("Unknown")
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
variantNumberOfMutationsString := helpers.ConvertIntToString(genomeNumberOfMutations)
|
|
|
|
return variantNumberOfMutationsString
|
|
|
|
}
|
|
|
|
|
|
|
|
numberOfVariantMutationsString := getNumberOfVariantMutationsString()
|
|
|
|
|
|
|
|
genomeNumberOfMutationsLabel := getBoldLabelCentered(numberOfVariantMutationsString)
|
|
|
|
numberOfMutationsColumn.Add(genomeNumberOfMutationsLabel)
|
|
|
|
|
|
|
|
viewMutationButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
|
2024-06-02 10:43:39 +02:00
|
|
|
setViewPersonGeneticAnalysisMonogenicDiseaseVariantDetailsPage(window, geneticAnalysisObject, diseaseName, variantIdentifier, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
viewButtonsColumn.Add(viewMutationButton)
|
|
|
|
|
|
|
|
variantNameColumn.Add(widget.NewSeparator())
|
|
|
|
genomeHasMutationColumn.Add(widget.NewSeparator())
|
|
|
|
numberOfMutationsColumn.Add(widget.NewSeparator())
|
|
|
|
viewButtonsColumn.Add(widget.NewSeparator())
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
variantsList_2Mutations := make([]string, 0)
|
|
|
|
variantsList_1Mutation := make([]string, 0)
|
|
|
|
variantsList_0Mutations := make([]string, 0)
|
|
|
|
variantsList_Unknown := make([]string, 0)
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
for variantIdentifierHex, _ := range diseaseVariantsMap{
|
|
|
|
|
|
|
|
variantIdentifier, err := encoding.DecodeHexStringTo3ByteArray(variantIdentifierHex)
|
|
|
|
if (err != nil) { return nil, err }
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
numberOfMutationsIsKnown, genomeNumberOfMutations, err := readGeneticAnalysis.GetPersonMonogenicDiseaseVariantInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, variantIdentifier, genomeIdentifier)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
if (numberOfMutationsIsKnown == false){
|
2024-06-02 10:43:39 +02:00
|
|
|
variantsList_Unknown = append(variantsList_Unknown, variantIdentifierHex)
|
2024-04-11 15:51:56 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
if (genomeNumberOfMutations == 0){
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
variantsList_0Mutations = append(variantsList_0Mutations, variantIdentifierHex)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
} else if (genomeNumberOfMutations == 1) {
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
variantsList_1Mutation = append(variantsList_1Mutation, variantIdentifierHex)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
} else if (genomeNumberOfMutations == 2){
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
variantsList_2Mutations = append(variantsList_2Mutations, variantIdentifierHex)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
} else {
|
|
|
|
return nil, errors.New("GetPersonMonogenicDiseaseVariantInfoFromGeneticAnalysis returning invalid genome number of mutations")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Items within each group are sorted so they will display the same way whenever user refreshes page
|
|
|
|
|
|
|
|
helpers.SortStringListToUnicodeOrder(variantsList_2Mutations)
|
|
|
|
helpers.SortStringListToUnicodeOrder(variantsList_1Mutation)
|
|
|
|
helpers.SortStringListToUnicodeOrder(variantsList_0Mutations)
|
|
|
|
helpers.SortStringListToUnicodeOrder(variantsList_Unknown)
|
|
|
|
|
|
|
|
for _, variantIdentifier := range variantsList_2Mutations{
|
|
|
|
|
|
|
|
err = addVariantRow(variantIdentifier)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
}
|
|
|
|
for _, variantIdentifier := range variantsList_1Mutation{
|
|
|
|
|
|
|
|
err = addVariantRow(variantIdentifier)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
}
|
|
|
|
for _, variantIdentifier := range variantsList_0Mutations{
|
|
|
|
|
|
|
|
err = addVariantRow(variantIdentifier)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
}
|
|
|
|
for _, variantIdentifier := range variantsList_Unknown{
|
|
|
|
|
|
|
|
err = addVariantRow(variantIdentifier)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeHasMutationHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setGenomeHasMonogenicDiseaseVariantMutationExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
genomeHasMutationColumn.Add(genomeHasMutationHelpButton)
|
|
|
|
|
|
|
|
genomeNumberOfMutationsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setMonogenicDiseaseVariantsExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
numberOfMutationsColumn.Add(genomeNumberOfMutationsHelpButton)
|
|
|
|
|
|
|
|
|
|
|
|
variantsGrid := container.NewHBox(layout.NewSpacer(), variantNameColumn, genomeHasMutationColumn, numberOfMutationsColumn, viewButtonsColumn, layout.NewSpacer())
|
|
|
|
|
|
|
|
return variantsGrid, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
variantsGrid, err := getVariantsGrid()
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1Row, widget.NewSeparator(), genomeNameRow, widget.NewSeparator(), variantsTestedRow, widget.NewSeparator(), phasedLociRow, widget.NewSeparator(), variantsGrid)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This page will show the details of a specific variant from a person's genetic analysis
|
|
|
|
// It will show the variant details for all of the person's genomes
|
2024-06-02 10:43:39 +02:00
|
|
|
func setViewPersonGeneticAnalysisMonogenicDiseaseVariantDetailsPage(window fyne.Window, geneticAnalysisObject geneticAnalysis.PersonAnalysis, diseaseName string, variantIdentifier [3]byte, previousPage func()){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
currentPage := func(){setViewPersonGeneticAnalysisMonogenicDiseaseVariantDetailsPage(window, geneticAnalysisObject, diseaseName, variantIdentifier, previousPage)}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
title := getPageTitleCentered("Monogenic Disease Variant Details - " + diseaseName)
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
variantIdentifierHex := encoding.EncodeBytesToHexString(variantIdentifier[:])
|
|
|
|
|
|
|
|
variantObject, err := monogenicDiseases.GetMonogenicDiseaseVariantObject(diseaseName, variantIdentifierHex)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) {
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
variantName := variantObject.VariantNames[0]
|
|
|
|
|
|
|
|
description := getLabelCentered("Below is the variant status for the person's genomes.")
|
|
|
|
|
|
|
|
variantNameLabel := widget.NewLabel("Variant Name:")
|
|
|
|
variantNameText := getBoldLabel(variantName)
|
|
|
|
variantNameHelpButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){
|
2024-06-02 10:43:39 +02:00
|
|
|
setViewMonogenicDiseaseVariantDetailsPage(window, diseaseName, variantIdentifierHex, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
variantNameRow := container.NewHBox(layout.NewSpacer(), variantNameLabel, variantNameText, variantNameHelpButton, layout.NewSpacer())
|
|
|
|
|
|
|
|
getGenomesHaveVariantGrid := func()(*fyne.Container, error){
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, onlyIncludeSharedGenomeIdentifier, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(geneticAnalysisObject)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
genomeNameLabel := getItalicLabelCentered("Genome Name")
|
|
|
|
genomeHasMutationLabel := getItalicLabelCentered("Genome Has Mutation")
|
|
|
|
numberOfMutationsLabel := getItalicLabelCentered("Number of Mutations")
|
|
|
|
|
|
|
|
genomeNameColumn := container.NewVBox(genomeNameLabel, widget.NewSeparator())
|
|
|
|
genomeHasMutationColumn := container.NewVBox(genomeHasMutationLabel, widget.NewSeparator())
|
|
|
|
numberOfMutationsColumn := container.NewVBox(numberOfMutationsLabel, widget.NewSeparator())
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
addGenomeRow := func(genomeName string, genomeIdentifier [16]byte, isACombinedGenome bool)error{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
genomeMutationsKnown, genomeNumberOfMutations, err := readGeneticAnalysis.GetPersonMonogenicDiseaseVariantInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, variantIdentifier, genomeIdentifier)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
getGenomeNameCell := func()*fyne.Container{
|
|
|
|
if (isACombinedGenome == false){
|
|
|
|
|
|
|
|
genomeNameLabel := getBoldLabelCentered(genomeName)
|
|
|
|
return genomeNameLabel
|
|
|
|
}
|
|
|
|
viewHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setCombinedGenomesExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
|
|
|
|
genomeNameLabel := getBoldLabel(genomeName)
|
|
|
|
genomeNameCell := container.NewHBox(layout.NewSpacer(), viewHelpButton, genomeNameLabel, layout.NewSpacer())
|
|
|
|
|
|
|
|
return genomeNameCell
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeNameCell := getGenomeNameCell()
|
|
|
|
genomeNameColumn.Add(genomeNameCell)
|
|
|
|
|
|
|
|
getGenomeHasMutationText := func()string{
|
|
|
|
if (genomeMutationsKnown == false){
|
|
|
|
result := translate("Unknown")
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
if (genomeNumberOfMutations == 0){
|
|
|
|
result := translate("No")
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
result := translate("Yes")
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeHasMutationText := getGenomeHasMutationText()
|
|
|
|
|
|
|
|
getGenomeNumberOfMutationsText := func()string{
|
|
|
|
if (genomeMutationsKnown == false){
|
|
|
|
result := translate("Unknown")
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeNumberOfMutationsString := helpers.ConvertIntToString(genomeNumberOfMutations)
|
|
|
|
|
|
|
|
return genomeNumberOfMutationsString
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeNumberOfMutationsText := getGenomeNumberOfMutationsText()
|
|
|
|
|
|
|
|
genomeHasMutationLabel := getBoldLabelCentered(genomeHasMutationText)
|
|
|
|
genomeHasMutationColumn.Add(genomeHasMutationLabel)
|
|
|
|
|
|
|
|
genomeNumberOfMutationsLabel := getBoldLabelCentered(genomeNumberOfMutationsText)
|
|
|
|
numberOfMutationsColumn.Add(genomeNumberOfMutationsLabel)
|
|
|
|
|
|
|
|
genomeNameColumn.Add(widget.NewSeparator())
|
|
|
|
genomeHasMutationColumn.Add(widget.NewSeparator())
|
|
|
|
numberOfMutationsColumn.Add(widget.NewSeparator())
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
|
|
|
|
err := addGenomeRow("Only Exclude Conflicts", onlyExcludeConflictsGenomeIdentifier, true)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
err = addGenomeRow("Only Include Shared", onlyIncludeSharedGenomeIdentifier, true)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, genomeIdentifier := range allRawGenomeIdentifiersList{
|
|
|
|
|
|
|
|
getGenomeName := func()(string, error){
|
|
|
|
|
|
|
|
genomeFound, _, timeGenomeWasExported, _, _, _, companyName, _, _, err := myGenomes.GetMyRawGenomeMetadata(genomeIdentifier)
|
|
|
|
if (err != nil) { return "", err }
|
|
|
|
if (genomeFound == false){
|
2024-06-02 10:43:39 +02:00
|
|
|
return "", errors.New("MyGenomeInfo for genome from analysisObject not found.")
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (multipleGenomesExist == false){
|
|
|
|
return companyName, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// We show the date that the genome was exported
|
|
|
|
|
|
|
|
exportTimeAgo, err := helpers.ConvertUnixTimeToTimeAgoTranslated(timeGenomeWasExported, false)
|
|
|
|
if (err != nil){ return "", err }
|
|
|
|
|
|
|
|
genomeName := companyName + " (Exported " + exportTimeAgo + ")"
|
|
|
|
|
|
|
|
return genomeName, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeName, err := getGenomeName()
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
err = addGenomeRow(genomeName, genomeIdentifier, false)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeHasMutationHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setGenomeHasMonogenicDiseaseVariantMutationExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
genomeHasMutationColumn.Add(genomeHasMutationHelpButton)
|
|
|
|
|
|
|
|
genomeNumberOfMutationsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setMonogenicDiseaseVariantsExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
numberOfMutationsColumn.Add(genomeNumberOfMutationsHelpButton)
|
|
|
|
|
|
|
|
genomesContainer := container.NewHBox(layout.NewSpacer(), genomeNameColumn, genomeHasMutationColumn, numberOfMutationsColumn, layout.NewSpacer())
|
|
|
|
|
|
|
|
return genomesContainer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genomesHaveVariantGrid, err := getGenomesHaveVariantGrid()
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), variantNameRow, widget.NewSeparator(), genomesHaveVariantGrid)
|
|
|
|
|
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
func setViewPersonGeneticAnalysisPolygenicDiseasesPage(window fyne.Window, personIdentifier string, analysisObject geneticAnalysis.PersonAnalysis, previousPage func()){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
currentPage := func(){setViewPersonGeneticAnalysisPolygenicDiseasesPage(window, personIdentifier, analysisObject, previousPage)}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
title := getPageTitleCentered("Viewing Genetic Analysis - Polygenic Diseases")
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
|
|
|
|
description := getLabelCentered("Below is an analysis of the polygenic disease risks for this person's genome.")
|
|
|
|
|
|
|
|
getPolygenicDiseasesContainer := func()(*fyne.Container, error){
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, _, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(analysisObject)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
// Outputs:
|
2024-06-02 10:43:39 +02:00
|
|
|
// -[16]byte: Main genome identifier (Is either the combined Only exclude conflicts genome or the only genome)
|
2024-04-11 15:51:56 +02:00
|
|
|
// -error
|
2024-06-02 10:43:39 +02:00
|
|
|
getMainGenomeIdentifier := func()([16]byte, error){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
return onlyExcludeConflictsGenomeIdentifier, nil
|
|
|
|
}
|
|
|
|
// Only 1 genome exists
|
|
|
|
|
|
|
|
genomeIdentifier := allRawGenomeIdentifiersList[0]
|
|
|
|
|
|
|
|
return genomeIdentifier, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
mainGenomeIdentifier, err := getMainGenomeIdentifier()
|
|
|
|
if (err != nil){ return nil, err }
|
2024-08-13 15:25:47 +02:00
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
diseaseNameLabel := getItalicLabelCentered("Disease Name")
|
|
|
|
|
|
|
|
riskScoreLabel := getItalicLabelCentered("Risk Score")
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
confidenceRangeLabel := getItalicLabelCentered("Confidence Range")
|
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
conflictExistsLabel := getItalicLabelCentered("Conflict Exists?")
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
emptyLabel5 := widget.NewLabel("")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
diseaseNameColumn := container.NewVBox(diseaseNameLabel, widget.NewSeparator())
|
|
|
|
riskScoreColumn := container.NewVBox(riskScoreLabel, widget.NewSeparator())
|
2024-08-13 15:25:47 +02:00
|
|
|
confidenceRangeColumn := container.NewVBox(confidenceRangeLabel, widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
conflictExistsColumn := container.NewVBox(conflictExistsLabel, widget.NewSeparator())
|
2024-08-13 15:25:47 +02:00
|
|
|
viewButtonsColumn := container.NewVBox(emptyLabel5, widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
polygenicDiseasesList, err := polygenicDiseases.GetPolygenicDiseaseObjectsList()
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
for _, diseaseObject := range polygenicDiseasesList{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
diseaseName := diseaseObject.DiseaseName
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-15 14:14:23 +02:00
|
|
|
neuralNetworkExists := trainedPredictionModels.CheckIfAttributeNeuralNetworkExists(diseaseName)
|
2024-08-13 15:25:47 +02:00
|
|
|
if (neuralNetworkExists == false){
|
|
|
|
// We can't analyze this trait
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
diseaseNameLabel := getBoldLabelCentered(diseaseName)
|
|
|
|
|
|
|
|
analysisExists, personRiskScore, predictionConfidenceRangesMap, _, _, conflictExists, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(analysisObject, diseaseName, mainGenomeIdentifier)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
getPersonRiskScoreLabel := func()fyne.Widget{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
if (analysisExists == false){
|
|
|
|
result := widget.NewLabel(translate("Unknown"))
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
riskScoreString := helpers.ConvertIntToString(personRiskScore)
|
|
|
|
riskScoreFormatted := riskScoreString + "/10"
|
|
|
|
|
|
|
|
riskScoreLabel := getBoldLabel(riskScoreFormatted)
|
|
|
|
|
|
|
|
return riskScoreLabel
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
personRiskScoreLabel := getPersonRiskScoreLabel()
|
|
|
|
personRiskScoreLabelCentered := getWidgetCentered(personRiskScoreLabel)
|
|
|
|
|
|
|
|
getConfidenceRangeLabel := func()(fyne.Widget, error){
|
|
|
|
|
|
|
|
if (analysisExists == false){
|
|
|
|
unknownLabel := widget.NewLabel("Unknown")
|
|
|
|
return unknownLabel, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is a list of the percentage accuracies in the map
|
|
|
|
// For example: 80% == The distance from the prediction you must travel for 80% of the predictions to be
|
|
|
|
// accurate within that range
|
|
|
|
confidenceRangePercentagesList := helpers.GetListOfMapKeys(predictionConfidenceRangesMap)
|
|
|
|
|
|
|
|
// We sort the list so the percentage is always the same upon refreshing the page
|
|
|
|
slices.Sort(confidenceRangePercentagesList)
|
|
|
|
|
|
|
|
closestToEightyPercentage, err := helpers.GetClosestIntInList(confidenceRangePercentagesList, 80)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
closestToEightyPercentageConfidenceDistance, exists := predictionConfidenceRangesMap[closestToEightyPercentage]
|
|
|
|
if (exists == false){
|
|
|
|
return nil, errors.New("GetListOfMapKeys returning list of elements which contains element which is not in the map.")
|
|
|
|
}
|
|
|
|
|
|
|
|
closestConfidenceDistanceString := helpers.ConvertFloat64ToStringRounded(closestToEightyPercentageConfidenceDistance, 2)
|
|
|
|
|
|
|
|
closestToEightyPercentageString := helpers.ConvertIntToString(closestToEightyPercentage)
|
|
|
|
|
|
|
|
confidenceRangeLabelValueFormatted := "+/- " + closestConfidenceDistanceString + " (" + closestToEightyPercentageString + "%)"
|
|
|
|
|
|
|
|
confidenceRangeLabel := getBoldLabel(confidenceRangeLabelValueFormatted)
|
|
|
|
|
|
|
|
return confidenceRangeLabel, nil
|
|
|
|
}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
confidenceRangeLabel, err := getConfidenceRangeLabel()
|
|
|
|
if (err != nil) { return nil, err }
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
conflictExistsString := helpers.ConvertBoolToYesOrNoString(conflictExists)
|
|
|
|
conflictExistsLabel := getBoldLabelCentered(conflictExistsString)
|
|
|
|
|
|
|
|
viewDetailsButton := getWidgetCentered(widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
|
2024-06-02 10:43:39 +02:00
|
|
|
setViewPersonGeneticAnalysisPolygenicDiseaseDetailsPage(window, personIdentifier, analysisObject, diseaseName, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
}))
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
diseaseNameColumn.Add(diseaseNameLabel)
|
|
|
|
riskScoreColumn.Add(personRiskScoreLabelCentered)
|
|
|
|
confidenceRangeColumn.Add(confidenceRangeLabel)
|
2024-04-11 15:51:56 +02:00
|
|
|
conflictExistsColumn.Add(conflictExistsLabel)
|
|
|
|
viewButtonsColumn.Add(viewDetailsButton)
|
|
|
|
|
|
|
|
diseaseNameColumn.Add(widget.NewSeparator())
|
|
|
|
riskScoreColumn.Add(widget.NewSeparator())
|
2024-08-13 15:25:47 +02:00
|
|
|
confidenceRangeColumn.Add(widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
conflictExistsColumn.Add(widget.NewSeparator())
|
|
|
|
viewButtonsColumn.Add(widget.NewSeparator())
|
|
|
|
}
|
|
|
|
|
|
|
|
riskScoreHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setPolygenicDiseaseRiskScoreExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
riskScoreColumn.Add(riskScoreHelpButton)
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
confidenceRangeHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
//TODO
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
})
|
|
|
|
confidenceRangeColumn.Add(confidenceRangeHelpButton)
|
|
|
|
|
|
|
|
diseasesContainer := container.NewHBox(layout.NewSpacer(), diseaseNameColumn, riskScoreColumn, confidenceRangeColumn)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
|
|
|
|
conflictExistsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setPersonGeneticAnalysisConflictExistsExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
|
|
|
|
conflictExistsColumn.Add(conflictExistsHelpButton)
|
|
|
|
diseasesContainer.Add(conflictExistsColumn)
|
|
|
|
}
|
|
|
|
|
|
|
|
diseasesContainer.Add(viewButtonsColumn)
|
|
|
|
diseasesContainer.Add(layout.NewSpacer())
|
|
|
|
|
|
|
|
return diseasesContainer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
diseasesContainer, err := getPolygenicDiseasesContainer()
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), diseasesContainer)
|
|
|
|
|
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
func setViewPersonGeneticAnalysisPolygenicDiseaseDetailsPage(window fyne.Window, personIdentifier string, analysisObject geneticAnalysis.PersonAnalysis, diseaseName string, previousPage func()){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
currentPage := func(){setViewPersonGeneticAnalysisPolygenicDiseaseDetailsPage(window, personIdentifier, analysisObject, diseaseName, previousPage)}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
title := getPageTitleCentered("Viewing Genetic Analysis - " + diseaseName)
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
2024-08-13 15:25:47 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, onlyIncludeSharedGenomeIdentifier, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(analysisObject)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) {
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
getDescriptionSection := func()*fyne.Container{
|
|
|
|
|
|
|
|
if (multipleGenomesExist == false){
|
|
|
|
description := getLabelCentered("Below is the disease information for this person's genome.")
|
|
|
|
|
|
|
|
return description
|
|
|
|
}
|
|
|
|
|
|
|
|
description1 := getLabelCentered("Below is the disease information for this person's genomes.")
|
|
|
|
description2 := getLabelCentered("The first two genomes are created by combining multiple genomes.")
|
2024-08-13 15:25:47 +02:00
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
descriptionsSection := container.NewVBox(description1, description2)
|
|
|
|
|
|
|
|
return descriptionsSection
|
|
|
|
}
|
|
|
|
|
|
|
|
descriptionSection := getDescriptionSection()
|
|
|
|
|
|
|
|
diseaseNameLabel := widget.NewLabel("Disease:")
|
|
|
|
diseaseNameText := getBoldLabel(diseaseName)
|
|
|
|
diseaseInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){
|
|
|
|
setViewPolygenicDiseaseDetailsPage(window, diseaseName, currentPage)
|
|
|
|
})
|
|
|
|
diseaseNameRow := container.NewHBox(layout.NewSpacer(), diseaseNameLabel, diseaseNameText, diseaseInfoButton, layout.NewSpacer())
|
|
|
|
|
|
|
|
getGenomesContainer := func()(*fyne.Container, error){
|
2024-06-02 10:43:39 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
diseaseObject, err := polygenicDiseases.GetPolygenicDiseaseObject(diseaseName)
|
2024-06-02 10:43:39 +02:00
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
diseaseLociList := diseaseObject.LociList
|
2024-06-02 10:43:39 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
totalQuantityOfLoci := len(diseaseLociList)
|
|
|
|
totalQuantityOfLociString := helpers.ConvertIntToString(totalQuantityOfLoci)
|
|
|
|
|
|
|
|
emptyLabel1 := widget.NewLabel("")
|
2024-04-11 15:51:56 +02:00
|
|
|
genomeNameLabel := getItalicLabelCentered("Genome Name")
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
emptyLabel2 := widget.NewLabel("")
|
2024-04-11 15:51:56 +02:00
|
|
|
riskScoreLabel := getItalicLabelCentered("Risk Score")
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
emptyLabel3 := widget.NewLabel("")
|
|
|
|
predictionConfidenceLabel := getItalicLabelCentered("Confidence Range")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
quantityOfLabel := getItalicLabelCentered("Quantity of")
|
|
|
|
lociKnownLabel := getItalicLabelCentered("Loci Known")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
emptyLabel4 := widget.NewLabel("")
|
|
|
|
emptyLabel5 := widget.NewLabel("")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
emptyLabel6 := widget.NewLabel("")
|
|
|
|
emptyLabel7 := widget.NewLabel("")
|
|
|
|
|
|
|
|
genomeNameColumn := container.NewVBox(emptyLabel1, genomeNameLabel, widget.NewSeparator())
|
|
|
|
riskScoreColumn := container.NewVBox(emptyLabel2, riskScoreLabel, widget.NewSeparator())
|
|
|
|
predictionConfidenceColumn := container.NewVBox(emptyLabel3, predictionConfidenceLabel, widget.NewSeparator())
|
|
|
|
quantityOfLociKnownColumn := container.NewVBox(quantityOfLabel, lociKnownLabel, widget.NewSeparator())
|
|
|
|
viewLifetimeRiskButtonsColumn := container.NewVBox(emptyLabel4, emptyLabel5, widget.NewSeparator())
|
|
|
|
viewDetailsButtonsColumn := container.NewVBox(emptyLabel6, emptyLabel7, widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
addGenomeRow := func(genomeName string, genomeIdentifier [16]byte, isACombinedGenome bool)error{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
getGenomeNameCell := func()*fyne.Container{
|
|
|
|
if (isACombinedGenome == false){
|
|
|
|
|
|
|
|
genomeNameLabel := getBoldLabelCentered(genomeName)
|
|
|
|
return genomeNameLabel
|
|
|
|
}
|
|
|
|
viewHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setCombinedGenomesExplainerPage(window, currentPage)
|
|
|
|
})
|
2024-07-19 19:16:28 +02:00
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
genomeNameLabel := getBoldLabel(genomeName)
|
|
|
|
genomeNameCell := container.NewHBox(layout.NewSpacer(), viewHelpButton, genomeNameLabel, layout.NewSpacer())
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
return genomeNameCell
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
genomeNameCell := getGenomeNameCell()
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
analysisExists, predictedRiskScore, predictionConfidenceRangesMap, quantityOfLociKnown, _, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(analysisObject, diseaseName, genomeIdentifier)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return err }
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
getRiskScoreLabel := func()fyne.Widget{
|
|
|
|
|
|
|
|
if (analysisExists == false){
|
|
|
|
|
|
|
|
result := widget.NewLabel(translate("Unknown"))
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
riskScoreString := helpers.ConvertIntToString(predictedRiskScore)
|
|
|
|
riskScoreFormatted := riskScoreString + "/10"
|
|
|
|
|
|
|
|
riskScoreLabel := getBoldLabel(riskScoreFormatted)
|
|
|
|
|
|
|
|
return riskScoreLabel
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeRiskScoreLabel := getRiskScoreLabel()
|
|
|
|
genomeRiskScoreLabelCentered := getWidgetCentered(genomeRiskScoreLabel)
|
|
|
|
|
|
|
|
getConfidenceRangeLabel := func()(fyne.Widget, error){
|
|
|
|
|
|
|
|
if (analysisExists == false){
|
|
|
|
unknownLabel := widget.NewLabel("Unknown")
|
|
|
|
return unknownLabel, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is a list of the percentage accuracies in the map
|
|
|
|
// For example: 80% == The distance from the prediction you must travel for 80% of the predictions to be
|
|
|
|
// accurate within that range
|
|
|
|
confidenceRangePercentagesList := helpers.GetListOfMapKeys(predictionConfidenceRangesMap)
|
|
|
|
|
|
|
|
// We sort the list so the percentage is always the same upon refreshing the page
|
|
|
|
slices.Sort(confidenceRangePercentagesList)
|
|
|
|
|
|
|
|
closestToEightyPercentage, err := helpers.GetClosestIntInList(confidenceRangePercentagesList, 80)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
closestToEightyPercentageConfidenceDistance, exists := predictionConfidenceRangesMap[closestToEightyPercentage]
|
|
|
|
if (exists == false){
|
|
|
|
return nil, errors.New("GetListOfMapKeys returning list of elements which contains element which is not in the map.")
|
|
|
|
}
|
|
|
|
|
|
|
|
closestConfidenceDistanceString := helpers.ConvertFloat64ToStringRounded(closestToEightyPercentageConfidenceDistance, 2)
|
|
|
|
|
|
|
|
closestToEightyPercentageString := helpers.ConvertIntToString(closestToEightyPercentage)
|
|
|
|
|
|
|
|
confidenceRangeLabelValueFormatted := "+/- " + closestConfidenceDistanceString + " (" + closestToEightyPercentageString + "%)"
|
|
|
|
|
|
|
|
confidenceRangeLabel := getBoldLabel(confidenceRangeLabelValueFormatted)
|
|
|
|
|
|
|
|
return confidenceRangeLabel, nil
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
confidenceRangeLabel, err := getConfidenceRangeLabel()
|
|
|
|
if (err != nil) { return err }
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
confidenceRangeLabelCentered := getWidgetCentered(confidenceRangeLabel)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
genomeQuantityOfLociKnownString := helpers.ConvertIntToString(quantityOfLociKnown)
|
|
|
|
quantityOfLociKnownLabel := getBoldLabelCentered(genomeQuantityOfLociKnownString + "/" + totalQuantityOfLociString)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
viewLifetimeRiskButton := widget.NewButtonWithIcon("", theme.HistoryIcon(), func(){
|
|
|
|
|
|
|
|
personFound, _, _, personSex, err := myPeople.GetPersonInfo(personIdentifier)
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, currentPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (personFound == false){
|
|
|
|
setErrorEncounteredPage(window, errors.New("setViewPersonGeneticAnalysisPolygenicDiseaseDetailsPage called with unknown personIdentifier"), currentPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
getSexToDisplay := func()string{
|
|
|
|
if (personSex == "Male" || personSex == "Female"){
|
|
|
|
return personSex
|
|
|
|
}
|
|
|
|
return "Male"
|
|
|
|
}
|
|
|
|
sexToDisplay := getSexToDisplay()
|
|
|
|
|
|
|
|
setViewPersonPolygenicDiseaseLifetimeProbabilitiesPage(window, diseaseName, genomeName, sexToDisplay, currentPage)
|
|
|
|
})
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
viewDetailsButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
|
|
|
|
//TODO
|
|
|
|
showUnderConstructionDialog(window)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
genomeNameColumn.Add(genomeNameCell)
|
2024-08-13 15:25:47 +02:00
|
|
|
riskScoreColumn.Add(genomeRiskScoreLabelCentered)
|
|
|
|
predictionConfidenceColumn.Add(confidenceRangeLabelCentered)
|
|
|
|
quantityOfLociKnownColumn.Add(quantityOfLociKnownLabel)
|
2024-04-11 15:51:56 +02:00
|
|
|
viewLifetimeRiskButtonsColumn.Add(viewLifetimeRiskButton)
|
2024-08-13 15:25:47 +02:00
|
|
|
viewDetailsButtonsColumn.Add(viewDetailsButton)
|
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
genomeNameColumn.Add(widget.NewSeparator())
|
|
|
|
riskScoreColumn.Add(widget.NewSeparator())
|
2024-08-13 15:25:47 +02:00
|
|
|
predictionConfidenceColumn.Add(widget.NewSeparator())
|
|
|
|
quantityOfLociKnownColumn.Add(widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
viewLifetimeRiskButtonsColumn.Add(widget.NewSeparator())
|
2024-08-13 15:25:47 +02:00
|
|
|
viewDetailsButtonsColumn.Add(widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
|
|
|
|
err := addGenomeRow("Only Exclude Conflicts", onlyExcludeConflictsGenomeIdentifier, true)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
err = addGenomeRow("Only Include Shared", onlyIncludeSharedGenomeIdentifier, true)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, genomeIdentifier := range allRawGenomeIdentifiersList{
|
|
|
|
|
|
|
|
getGenomeName := func()(string, error){
|
|
|
|
genomeFound, _, timeGenomeWasExported, _, _, _, companyName, _, _, err := myGenomes.GetMyRawGenomeMetadata(genomeIdentifier)
|
|
|
|
if (err != nil) { return "", err }
|
|
|
|
if (genomeFound == false){
|
2024-06-02 10:43:39 +02:00
|
|
|
return "", errors.New("MyGenomeInfo for genome from analysisObject not found.")
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (multipleGenomesExist == false){
|
|
|
|
return companyName, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// We show the date the genome was exported
|
2024-08-13 15:25:47 +02:00
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
exportTimeAgo, err := helpers.ConvertUnixTimeToTimeAgoTranslated(timeGenomeWasExported, false)
|
|
|
|
if (err != nil){ return "", err }
|
|
|
|
|
|
|
|
genomeName := companyName + " (Exported " + exportTimeAgo + ")"
|
|
|
|
|
|
|
|
return genomeName, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeName, err := getGenomeName()
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
err = addGenomeRow(genomeName, genomeIdentifier, false)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
}
|
|
|
|
|
|
|
|
riskScoreHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setPolygenicDiseaseRiskScoreExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
riskScoreColumn.Add(riskScoreHelpButton)
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
predictionConfidenceHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
})
|
|
|
|
predictionConfidenceColumn.Add(predictionConfidenceHelpButton)
|
|
|
|
|
|
|
|
quantityOfLociKnownHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
2024-04-11 15:51:56 +02:00
|
|
|
setPolygenicDiseaseNumberOfLociTestedExplainerPage(window, currentPage)
|
|
|
|
})
|
2024-08-13 15:25:47 +02:00
|
|
|
quantityOfLociKnownColumn.Add(quantityOfLociKnownHelpButton)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
genomesContainer := container.NewHBox(layout.NewSpacer(), genomeNameColumn, riskScoreColumn, predictionConfidenceColumn, quantityOfLociKnownColumn, viewLifetimeRiskButtonsColumn, viewDetailsButtonsColumn, layout.NewSpacer())
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
return genomesContainer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genomesContainer, err := getGenomesContainer()
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), descriptionSection, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), genomesContainer)
|
2024-08-13 15:25:47 +02:00
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func setViewPersonPolygenicDiseaseLifetimeProbabilitiesPage(window fyne.Window, diseaseName string, genomeName string, maleOrFemale string, previousPage func()){
|
|
|
|
|
|
|
|
currentPage := func(){setViewPersonPolygenicDiseaseLifetimeProbabilitiesPage(window, diseaseName, genomeName, maleOrFemale, previousPage)}
|
|
|
|
|
|
|
|
title := getPageTitleCentered("Viewing Disease Lifetime Probabilities")
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
|
|
|
|
description1 := getLabelCentered("Below are the lifetime probabilities for this disease.")
|
|
|
|
description2 := getLabelCentered("The average risk column describes the probability for the average person.")
|
|
|
|
|
|
|
|
//TODO: Once we understand how to calculate it, we will add adjusted risk column with estimated probability
|
|
|
|
|
|
|
|
getGenomeNameRow := func()*fyne.Container{
|
|
|
|
|
|
|
|
genomeLabel := widget.NewLabel("Genome:")
|
|
|
|
genomeNameLabel := getBoldLabel(genomeName)
|
|
|
|
|
|
|
|
if (genomeName == "Only Exclude Conflicts" || genomeName == "Only Include Shared"){
|
|
|
|
genomeHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setCombinedGenomesExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
genomeNameRow := container.NewHBox(layout.NewSpacer(), genomeLabel, genomeNameLabel, genomeHelpButton, layout.NewSpacer())
|
|
|
|
return genomeNameRow
|
|
|
|
}
|
|
|
|
genomeNameRow := container.NewHBox(layout.NewSpacer(), genomeLabel, genomeNameLabel, layout.NewSpacer())
|
|
|
|
return genomeNameRow
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeNameRow := getGenomeNameRow()
|
|
|
|
|
|
|
|
getTabContainer := func(tabMaleOrFemale string)(*container.TabItem, error){
|
|
|
|
|
|
|
|
ageLabel := getItalicLabelCentered("Age")
|
|
|
|
|
|
|
|
averageRiskLabel := getItalicLabelCentered("Average Risk")
|
|
|
|
|
|
|
|
ageColumn := container.NewVBox(ageLabel, widget.NewSeparator())
|
|
|
|
averageRiskColumn := container.NewVBox(averageRiskLabel, widget.NewSeparator())
|
|
|
|
|
|
|
|
diseaseObject, err := polygenicDiseases.GetPolygenicDiseaseObject(diseaseName)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
getAverageRiskProbabilitiesFunction := diseaseObject.GetAverageRiskProbabilitiesFunction
|
|
|
|
|
|
|
|
rowInitialValuesSet := false
|
|
|
|
rowInitialAge := 0
|
|
|
|
rowInitialAgeRisk := float64(0)
|
|
|
|
|
|
|
|
rowSummedRisks := float64(0)
|
|
|
|
|
|
|
|
for age := 0; age <= 110; age++{
|
|
|
|
|
|
|
|
ageRisk, err := getAverageRiskProbabilitiesFunction(tabMaleOrFemale, age)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
if (rowInitialValuesSet == false){
|
|
|
|
rowInitialValuesSet = true
|
|
|
|
rowInitialAge = age
|
|
|
|
rowInitialAgeRisk = ageRisk
|
|
|
|
rowSummedRisks = ageRisk
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
rowSummedRisks += ageRisk
|
|
|
|
|
|
|
|
nextAge := age+1
|
|
|
|
if (nextAge % 10 != 0){
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if (age < 109 && rowInitialAgeRisk == ageRisk){
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// We make a new row
|
|
|
|
|
|
|
|
averageRisk := rowSummedRisks / float64(age - rowInitialAge + 1)
|
|
|
|
|
|
|
|
if (rowInitialAge >= age){
|
|
|
|
return nil, errors.New("rowInitialAge is >= age.")
|
|
|
|
}
|
|
|
|
|
|
|
|
startAgeString := helpers.ConvertIntToString(rowInitialAge)
|
|
|
|
endAgeString := helpers.ConvertIntToString(age)
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
averageRiskPercentage := averageRisk * 100
|
|
|
|
|
|
|
|
averageRiskString := helpers.ConvertFloat64ToStringRounded(averageRiskPercentage, 2)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
ageRangeLabel := getBoldLabel(startAgeString + " - " + endAgeString)
|
|
|
|
averageRiskLabel := getBoldLabelCentered(averageRiskString + "%")
|
|
|
|
|
|
|
|
ageColumn.Add(ageRangeLabel)
|
|
|
|
averageRiskColumn.Add(averageRiskLabel)
|
|
|
|
|
|
|
|
ageColumn.Add(widget.NewSeparator())
|
|
|
|
averageRiskColumn.Add(widget.NewSeparator())
|
|
|
|
|
|
|
|
rowInitialValuesSet = false
|
|
|
|
}
|
|
|
|
|
|
|
|
averageRiskHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setPolygenicDiseaseAverageLifetimeRiskExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
averageRiskColumn.Add(averageRiskHelpButton)
|
|
|
|
|
|
|
|
ageProbabilitiesGrid := container.NewHBox(layout.NewSpacer(), ageColumn, averageRiskColumn, layout.NewSpacer())
|
|
|
|
|
|
|
|
ageProbabilitiesTabItem := container.NewTabItem(tabMaleOrFemale, ageProbabilitiesGrid)
|
|
|
|
|
|
|
|
return ageProbabilitiesTabItem, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
maleTab, err := getTabContainer("Male")
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
femaleTab, err := getTabContainer("Female")
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
2024-08-13 15:25:47 +02:00
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
ageProbabilityTabs := container.NewAppTabs(maleTab, femaleTab)
|
|
|
|
|
|
|
|
if (maleOrFemale == "Male"){
|
|
|
|
ageProbabilityTabs.Select(maleTab)
|
|
|
|
} else {
|
|
|
|
ageProbabilityTabs.Select(femaleTab)
|
|
|
|
}
|
|
|
|
|
|
|
|
ageProbabilityTabsCentered := getContainerCentered(getAppTabsBoxed(ageProbabilityTabs))
|
|
|
|
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, widget.NewSeparator(), genomeNameRow, widget.NewSeparator(), ageProbabilityTabsCentered)
|
|
|
|
|
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
func setViewPersonGeneticAnalysisDiscreteTraitsPage(window fyne.Window, personIdentifier string, analysisObject geneticAnalysis.PersonAnalysis, previousPage func()){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
currentPage := func(){setViewPersonGeneticAnalysisDiscreteTraitsPage(window, personIdentifier, analysisObject, previousPage)}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
title := getPageTitleCentered("Viewing Genetic Analysis - Discrete Traits")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
description := getLabelCentered("Below is an analysis of the discrete traits for this person's genome.")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
getTraitsContainer := func()(*fyne.Container, error){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, _, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(analysisObject)
|
|
|
|
if (err != nil){ return nil, err }
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
// Outputs:
|
|
|
|
// -[16]byte: Main genome identifier (Is either the combined Only exclude conflicts genome or the only genome)
|
|
|
|
// -error
|
|
|
|
getMainGenomeIdentifier := func()([16]byte, error){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
return onlyExcludeConflictsGenomeIdentifier, nil
|
|
|
|
}
|
|
|
|
// Only 1 genome exists
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
genomeIdentifier := allRawGenomeIdentifiersList[0]
|
2024-06-02 10:43:39 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
return genomeIdentifier, nil
|
2024-06-02 10:43:39 +02:00
|
|
|
}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
mainGenomeIdentifier, err := getMainGenomeIdentifier()
|
|
|
|
if (err != nil){ return nil, err }
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
emptyLabel1 := widget.NewLabel("")
|
|
|
|
traitNameLabel := getItalicLabelCentered("Trait Name")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
emptyLabel2 := widget.NewLabel("")
|
|
|
|
predictedOutcomeLabel := getItalicLabelCentered("Predicted Outcome")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
quantityOfLabel := getItalicLabelCentered("Quantity Of")
|
|
|
|
lociKnownLabel := getItalicLabelCentered("Loci Known")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
emptyLabel3 := widget.NewLabel("")
|
|
|
|
conflictExistsLabel := getItalicLabelCentered("Conflict Exists?")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
emptyLabel4 := widget.NewLabel("")
|
|
|
|
emptyLabel5 := widget.NewLabel("")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
traitNameColumn := container.NewVBox(emptyLabel1, traitNameLabel, widget.NewSeparator())
|
|
|
|
predictedOutcomeColumn := container.NewVBox(emptyLabel2, predictedOutcomeLabel, widget.NewSeparator())
|
|
|
|
quantityOfLociKnownColumn := container.NewVBox(quantityOfLabel, lociKnownLabel, widget.NewSeparator())
|
|
|
|
conflictExistsColumn := container.NewVBox(emptyLabel3, conflictExistsLabel, widget.NewSeparator())
|
|
|
|
viewButtonsColumn := container.NewVBox(emptyLabel4, emptyLabel5, widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
traitObjectsList, err := traits.GetTraitObjectsList()
|
|
|
|
if (err != nil) { return nil, err }
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
for _, traitObject := range traitObjectsList{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
traitIsDiscreteOrNumeric := traitObject.DiscreteOrNumeric
|
|
|
|
if (traitIsDiscreteOrNumeric != "Discrete"){
|
|
|
|
continue
|
|
|
|
}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
traitName := traitObject.TraitName
|
|
|
|
traitLociList := traitObject.LociList
|
|
|
|
traitRulesList := traitObject.RulesList
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
if (len(traitLociList) == 0 && len(traitRulesList) == 0){
|
|
|
|
// This trait does not have any rules or loci to analyze
|
|
|
|
// We cannot analyze it yet
|
|
|
|
continue
|
|
|
|
}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
traitNameText := getBoldLabelCentered(traitName)
|
|
|
|
|
|
|
|
neuralNetworkExists, neuralNetworkAnalysisExists, neuralNetworkPredictedOutcome, _, quantityOfLociKnown_NeuralNetwork, _, anyRulesExist, rulesAnalysisExists, _, rulesPredictedOutcomeExists, rulesPredictedOutcome, _, quantityOfLociKnown_Rules, conflictExists, err := readGeneticAnalysis.GetPersonDiscreteTraitInfoFromGeneticAnalysis(analysisObject, traitName, mainGenomeIdentifier)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
if (neuralNetworkExists == false && anyRulesExist == false){
|
|
|
|
// We can't analyze this trait
|
|
|
|
continue
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
getPredictionLabel := func()fyne.Widget{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
if (neuralNetworkExists == true){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
if (neuralNetworkAnalysisExists == false){
|
|
|
|
result := getItalicLabel("Unknown")
|
|
|
|
return result
|
|
|
|
}
|
2024-06-02 10:43:39 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
result := getBoldLabel(neuralNetworkPredictedOutcome)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
// anyRulesExist must be true
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
if (rulesAnalysisExists == false || rulesPredictedOutcomeExists == false){
|
|
|
|
result := getItalicLabel("Unknown")
|
2024-04-11 15:51:56 +02:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
result := getBoldLabel(rulesPredictedOutcome)
|
|
|
|
|
|
|
|
return result
|
2024-07-19 19:16:28 +02:00
|
|
|
}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
predictionLabel := getPredictionLabel()
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
predictionLabelCentered := getWidgetCentered(predictionLabel)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
getQuantityOfLociKnown := func()int{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
if (neuralNetworkExists == true){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
return quantityOfLociKnown_NeuralNetwork
|
|
|
|
}
|
|
|
|
return quantityOfLociKnown_Rules
|
|
|
|
}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
quantityOfLociKnown := getQuantityOfLociKnown()
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
getTotalQuantityOfLoci := func()int{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
if (neuralNetworkExists == true){
|
|
|
|
|
|
|
|
totalQuantityOfLoci := len(traitLociList)
|
|
|
|
|
|
|
|
return totalQuantityOfLoci
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
2024-07-19 19:16:28 +02:00
|
|
|
|
|
|
|
traitLociList_Rules := traitObject.LociList_Rules
|
|
|
|
|
|
|
|
totalQuantityOfLoci := len(traitLociList_Rules)
|
|
|
|
|
|
|
|
return totalQuantityOfLoci
|
|
|
|
}
|
|
|
|
|
|
|
|
totalQuantityOfLoci := getTotalQuantityOfLoci()
|
|
|
|
|
|
|
|
quantityOfLociKnownString := helpers.ConvertIntToString(quantityOfLociKnown)
|
|
|
|
totalQuantityOfLociString := helpers.ConvertIntToString(totalQuantityOfLoci)
|
|
|
|
|
|
|
|
quantityOfLociKnownFormatted := quantityOfLociKnownString + "/" + totalQuantityOfLociString
|
|
|
|
|
|
|
|
quantityOfLociKnownLabel := getBoldLabelCentered(quantityOfLociKnownFormatted)
|
|
|
|
|
|
|
|
conflictExistsString := helpers.ConvertBoolToYesOrNoString(conflictExists)
|
|
|
|
conflictExistsLabel := getBoldLabelCentered(conflictExistsString)
|
|
|
|
|
|
|
|
viewDetailsButton := getWidgetCentered(widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
|
|
|
|
setViewPersonGeneticAnalysisDiscreteTraitDetailsPage(window, personIdentifier, analysisObject, traitName, currentPage)
|
|
|
|
}))
|
|
|
|
|
|
|
|
traitNameColumn.Add(traitNameText)
|
|
|
|
predictedOutcomeColumn.Add(predictionLabelCentered)
|
|
|
|
quantityOfLociKnownColumn.Add(quantityOfLociKnownLabel)
|
|
|
|
conflictExistsColumn.Add(conflictExistsLabel)
|
|
|
|
viewButtonsColumn.Add(viewDetailsButton)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
traitNameColumn.Add(widget.NewSeparator())
|
2024-07-19 19:16:28 +02:00
|
|
|
predictedOutcomeColumn.Add(widget.NewSeparator())
|
|
|
|
quantityOfLociKnownColumn.Add(widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
conflictExistsColumn.Add(widget.NewSeparator())
|
|
|
|
viewButtonsColumn.Add(widget.NewSeparator())
|
|
|
|
}
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
predictedOutcomeHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
//TODO
|
|
|
|
showUnderConstructionDialog(window)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
2024-07-19 19:16:28 +02:00
|
|
|
predictedOutcomeColumn.Add(predictedOutcomeHelpButton)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
quantityOfLociKnownHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
//TODO
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
})
|
|
|
|
quantityOfLociKnownColumn.Add(quantityOfLociKnownHelpButton)
|
|
|
|
|
|
|
|
traitsContainer := container.NewHBox(layout.NewSpacer(), traitNameColumn, predictedOutcomeColumn, quantityOfLociKnownColumn)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
|
|
|
|
conflictExistsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setPersonGeneticAnalysisConflictExistsExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
|
|
|
|
conflictExistsColumn.Add(conflictExistsHelpButton)
|
|
|
|
traitsContainer.Add(conflictExistsColumn)
|
|
|
|
}
|
|
|
|
|
|
|
|
traitsContainer.Add(viewButtonsColumn)
|
|
|
|
traitsContainer.Add(layout.NewSpacer())
|
|
|
|
|
|
|
|
return traitsContainer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
traitsContainer, err := getTraitsContainer()
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), traitsContainer)
|
|
|
|
|
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
func setViewPersonGeneticAnalysisDiscreteTraitDetailsPage(window fyne.Window, personIdentifier string, analysisObject geneticAnalysis.PersonAnalysis, traitName string, previousPage func()){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
currentPage := func(){setViewPersonGeneticAnalysisDiscreteTraitDetailsPage(window, personIdentifier, analysisObject, traitName, previousPage)}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
title := getPageTitleCentered("Viewing Genetic Analysis - " + traitName)
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
2024-08-13 15:25:47 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, onlyIncludeSharedGenomeIdentifier, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(analysisObject)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) {
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
getDescriptionSection := func()*fyne.Container{
|
|
|
|
|
|
|
|
if (multipleGenomesExist == false){
|
|
|
|
description := getLabelCentered("Below is the trait information for this person's genome.")
|
|
|
|
|
|
|
|
return description
|
|
|
|
}
|
|
|
|
|
|
|
|
description1 := getLabelCentered("Below is the trait information for this person's genomes.")
|
|
|
|
description2 := getLabelCentered("The first two genomes are created by combining multiple genomes.")
|
|
|
|
|
|
|
|
descriptionsSection := container.NewVBox(description1, description2)
|
|
|
|
|
|
|
|
return descriptionsSection
|
|
|
|
}
|
|
|
|
|
|
|
|
descriptionSection := getDescriptionSection()
|
|
|
|
|
|
|
|
traitNameLabel := widget.NewLabel("Trait:")
|
|
|
|
traitNameText := getBoldLabel(traitName)
|
|
|
|
traitInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){
|
|
|
|
setViewTraitDetailsPage(window, traitName, currentPage)
|
|
|
|
})
|
2024-07-19 19:16:28 +02:00
|
|
|
traitNameRow := container.NewHBox(layout.NewSpacer(), traitNameLabel, traitNameText, traitInfoButton, layout.NewSpacer())
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
getGenomesContainer := func()(*fyne.Container, error){
|
2024-06-02 10:43:39 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
traitObject, err := traits.GetTraitObject(traitName)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
emptyLabel1 := widget.NewLabel("")
|
2024-04-11 15:51:56 +02:00
|
|
|
genomeNameLabel := getItalicLabelCentered("Genome Name")
|
2024-07-19 19:16:28 +02:00
|
|
|
|
|
|
|
emptyLabel2 := widget.NewLabel("")
|
|
|
|
predictedOutcomeLabel := getItalicLabelCentered("Predicted Outcome")
|
|
|
|
|
|
|
|
emptyLabel3 := widget.NewLabel("")
|
|
|
|
predictionConfidenceLabel := getItalicLabelCentered("Prediction Confidence")
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
quantityOfLabel1 := getItalicLabelCentered("Quantity Of")
|
|
|
|
lociKnownLabel := getItalicLabelCentered("Loci Known")
|
|
|
|
|
|
|
|
quantityOfLabel2 := getItalicLabelCentered("Quantity Of")
|
2024-04-11 15:51:56 +02:00
|
|
|
rulesTestedLabel := getItalicLabelCentered("Rules Tested")
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
emptyLabel4 := widget.NewLabel("")
|
|
|
|
emptyLabel5 := widget.NewLabel("")
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
genomeNameColumn := container.NewVBox(emptyLabel1, genomeNameLabel, widget.NewSeparator())
|
|
|
|
predictedOutcomeColumn := container.NewVBox(emptyLabel2, predictedOutcomeLabel, widget.NewSeparator())
|
|
|
|
neuralNetworkPredictionConfidenceColumn := container.NewVBox(emptyLabel3, predictionConfidenceLabel, widget.NewSeparator())
|
|
|
|
quantityOfLociKnownColumn := container.NewVBox(quantityOfLabel1, lociKnownLabel, widget.NewSeparator())
|
|
|
|
numberOfRulesTestedColumn := container.NewVBox(quantityOfLabel2, rulesTestedLabel, widget.NewSeparator())
|
|
|
|
viewDetailsButtonsColumn := container.NewVBox(emptyLabel4, emptyLabel5, widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
addGenomeRow := func(genomeName string, genomeIdentifier [16]byte, isACombinedGenome bool)error{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
getGenomeNameCell := func()*fyne.Container{
|
|
|
|
if (isACombinedGenome == false){
|
|
|
|
|
|
|
|
genomeNameLabel := getBoldLabelCentered(genomeName)
|
|
|
|
return genomeNameLabel
|
|
|
|
}
|
|
|
|
viewHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setCombinedGenomesExplainerPage(window, currentPage)
|
|
|
|
})
|
2024-06-02 10:43:39 +02:00
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
genomeNameLabel := getBoldLabel(genomeName)
|
|
|
|
genomeNameCell := container.NewHBox(layout.NewSpacer(), viewHelpButton, genomeNameLabel, layout.NewSpacer())
|
2024-06-02 10:43:39 +02:00
|
|
|
|
|
|
|
return genomeNameCell
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
genomeNameCell := getGenomeNameCell()
|
2024-06-02 10:43:39 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
neuralNetworkExists, neuralNetworkAnalysisExists, neuralNetworkPredictedOutcome, neuralNetworkPredictionConfidence, quantityOfLociKnown_NeuralNetwork, _, anyRulesExist, rulesAnalysisExists, _, rulesPredictedOutcomeExists, rulesPredictedOutcome, quantityOfRulesTested, _, _, err := readGeneticAnalysis.GetPersonDiscreteTraitInfoFromGeneticAnalysis(analysisObject, traitName, genomeIdentifier)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return err }
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
if (neuralNetworkExists == false && anyRulesExist == false){
|
|
|
|
// This trait is not analyzable
|
|
|
|
return errors.New("setViewPersonGeneticAnalysisTraitDetailsPage called with trait which cannot be analyzed via neural networks and traits.")
|
|
|
|
}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
getPredictedOutcomeLabel := func()fyne.Widget{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
if (neuralNetworkExists == true){
|
|
|
|
if (neuralNetworkAnalysisExists == false){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
predictedOutcomeLabel := getItalicLabel("Unknown")
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
return predictedOutcomeLabel
|
|
|
|
}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
predictedOutcomeLabel := getBoldLabel(neuralNetworkPredictedOutcome)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
return predictedOutcomeLabel
|
|
|
|
}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
// anyRulesExist must be true
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
if (rulesAnalysisExists == false || rulesPredictedOutcomeExists == false){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
predictedOutcomeLabel := getItalicLabel("Unknown")
|
|
|
|
return predictedOutcomeLabel
|
|
|
|
}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
predictedOutcomeLabel := getBoldLabel(rulesPredictedOutcome)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
return predictedOutcomeLabel
|
|
|
|
}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
predictedOutcomeLabel := getPredictedOutcomeLabel()
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
predictedOutcomeLabelCentered := getWidgetCentered(predictedOutcomeLabel)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
if (neuralNetworkExists == true){
|
2024-07-19 19:16:28 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
if (neuralNetworkAnalysisExists == false){
|
2024-07-19 19:16:28 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
predictedOutcomeConfidenceLabel := getItalicLabelCentered("Unknown")
|
2024-07-19 19:16:28 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
neuralNetworkPredictionConfidenceColumn.Add(predictedOutcomeConfidenceLabel)
|
|
|
|
} else {
|
2024-07-19 19:16:28 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
neuralNetworkPredictionConfidenceString := helpers.ConvertIntToString(neuralNetworkPredictionConfidence)
|
|
|
|
predictedOutcomeConfidenceLabel := getBoldLabelCentered(neuralNetworkPredictionConfidenceString + "%")
|
2024-07-19 19:16:28 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
neuralNetworkPredictionConfidenceColumn.Add(predictedOutcomeConfidenceLabel)
|
2024-07-19 19:16:28 +02:00
|
|
|
}
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
traitLociList := traitObject.LociList
|
|
|
|
totalQuantityOfLoci := len(traitLociList)
|
2024-07-19 19:16:28 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
quantityOfLociKnownString := helpers.ConvertIntToString(quantityOfLociKnown_NeuralNetwork)
|
|
|
|
totalQuantityOfLociString := helpers.ConvertIntToString(totalQuantityOfLoci)
|
2024-07-19 19:16:28 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
quantityOfLociKnownFormatted := quantityOfLociKnownString + "/" + totalQuantityOfLociString
|
2024-07-19 19:16:28 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
quantityOfLociKnownLabel := getBoldLabelCentered(quantityOfLociKnownFormatted)
|
2024-07-19 19:16:28 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
quantityOfLociKnownColumn.Add(quantityOfLociKnownLabel)
|
2024-07-19 19:16:28 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
} else {
|
2024-07-19 19:16:28 +02:00
|
|
|
|
|
|
|
traitRulesMap, err := traits.GetTraitRulesMap(traitName)
|
2024-08-13 15:25:47 +02:00
|
|
|
if (err != nil){ return err }
|
2024-07-19 19:16:28 +02:00
|
|
|
|
|
|
|
totalNumberOfRules := len(traitRulesMap)
|
|
|
|
totalNumberOfRulesString := helpers.ConvertIntToString(totalNumberOfRules)
|
|
|
|
|
|
|
|
quantityOfRulesTestedString := helpers.ConvertIntToString(quantityOfRulesTested)
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
quantityOfRulesTestedLabel := getBoldLabelCentered(quantityOfRulesTestedString + "/" + totalNumberOfRulesString)
|
2024-07-19 19:16:28 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
numberOfRulesTestedColumn.Add(quantityOfRulesTestedLabel)
|
2024-07-19 19:16:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
viewDetailsButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
|
|
|
|
if (neuralNetworkExists == true){
|
|
|
|
//TODO
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
} else {
|
|
|
|
setViewPersonGenomeDiscreteTraitRulesPage(window, analysisObject, traitName, genomeIdentifier, genomeName, currentPage)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
genomeNameColumn.Add(genomeNameCell)
|
|
|
|
predictedOutcomeColumn.Add(predictedOutcomeLabelCentered)
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
viewDetailsButtonsColumn.Add(viewDetailsButton)
|
2024-04-11 15:51:56 +02:00
|
|
|
genomeNameColumn.Add(widget.NewSeparator())
|
2024-07-19 19:16:28 +02:00
|
|
|
predictedOutcomeColumn.Add(widget.NewSeparator())
|
|
|
|
neuralNetworkPredictionConfidenceColumn.Add(widget.NewSeparator())
|
2024-08-13 15:25:47 +02:00
|
|
|
quantityOfLociKnownColumn.Add(widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
numberOfRulesTestedColumn.Add(widget.NewSeparator())
|
2024-07-19 19:16:28 +02:00
|
|
|
viewDetailsButtonsColumn.Add(widget.NewSeparator())
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
|
|
|
|
err := addGenomeRow("Only Exclude Conflicts", onlyExcludeConflictsGenomeIdentifier, true)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
err = addGenomeRow("Only Include Shared", onlyIncludeSharedGenomeIdentifier, true)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, genomeIdentifier := range allRawGenomeIdentifiersList{
|
|
|
|
|
|
|
|
getGenomeName := func()(string, error){
|
|
|
|
|
|
|
|
genomeFound, _, timeGenomeWasExported, _, _, _, companyName, _, _, err := myGenomes.GetMyRawGenomeMetadata(genomeIdentifier)
|
|
|
|
if (err != nil) { return "", err }
|
|
|
|
if (genomeFound == false){
|
2024-06-02 10:43:39 +02:00
|
|
|
return "", errors.New("MyGenomeInfo for genome from analysisObject not found.")
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (multipleGenomesExist == false){
|
|
|
|
return companyName, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// We show the date that the genome was exported
|
|
|
|
|
|
|
|
exportTimeAgo, err := helpers.ConvertUnixTimeToTimeAgoTranslated(timeGenomeWasExported, false)
|
|
|
|
if (err != nil){ return "", err }
|
|
|
|
|
|
|
|
genomeName := companyName + " (Exported " + exportTimeAgo + ")"
|
|
|
|
|
|
|
|
return genomeName, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeName, err := getGenomeName()
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
err = addGenomeRow(genomeName, genomeIdentifier, false)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
}
|
|
|
|
|
2024-08-15 14:14:23 +02:00
|
|
|
neuralNetworkExists := trainedPredictionModels.CheckIfAttributeNeuralNetworkExists(traitName)
|
2024-08-13 15:25:47 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
if (neuralNetworkExists == true){
|
|
|
|
|
|
|
|
neuralNetworksHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setDiscreteTraitNeuralNetworkPredictionExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
predictedOutcomeColumn.Add(neuralNetworksHelpButton)
|
|
|
|
} else {
|
|
|
|
|
|
|
|
rulesHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setDiscreteTraitRulesPredictionExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
predictedOutcomeColumn.Add(rulesHelpButton)
|
|
|
|
}
|
|
|
|
|
|
|
|
neuralNetworkConfidenceHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
//TODO
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
2024-07-19 19:16:28 +02:00
|
|
|
neuralNetworkPredictionConfidenceColumn.Add(neuralNetworkConfidenceHelpButton)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
numberOfRulesTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
2024-07-19 19:16:28 +02:00
|
|
|
setDiscreteTraitQuantityOfRulesTestedExplainerPage(window, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
numberOfRulesTestedColumn.Add(numberOfRulesTestedHelpButton)
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
quantityOfLociKnownHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
//TODO
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
})
|
|
|
|
quantityOfLociKnownColumn.Add(quantityOfLociKnownHelpButton)
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
genomesContainer := container.NewHBox(layout.NewSpacer(), genomeNameColumn, predictedOutcomeColumn)
|
|
|
|
|
|
|
|
if (neuralNetworkExists == true){
|
|
|
|
genomesContainer.Add(neuralNetworkPredictionConfidenceColumn)
|
2024-08-13 15:25:47 +02:00
|
|
|
genomesContainer.Add(quantityOfLociKnownColumn)
|
2024-07-19 19:16:28 +02:00
|
|
|
} else {
|
|
|
|
genomesContainer.Add(numberOfRulesTestedColumn)
|
|
|
|
}
|
2024-08-13 15:25:47 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
genomesContainer.Add(viewDetailsButtonsColumn)
|
|
|
|
genomesContainer.Add(layout.NewSpacer())
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
return genomesContainer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genomesContainer, err := getGenomesContainer()
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), descriptionSection, widget.NewSeparator(), traitNameRow, widget.NewSeparator(), genomesContainer)
|
|
|
|
|
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
// Ths function provides a page to view the discrete trait rules for a particular genome from a genetic analysis
|
|
|
|
func setViewPersonGenomeDiscreteTraitRulesPage(window fyne.Window, geneticAnalysisObject geneticAnalysis.PersonAnalysis, traitName string, genomeIdentifier [16]byte, genomeName string, previousPage func()){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
setLoadingScreen(window, "Loading Trait Rules", "Loading trait rules...")
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
currentPage := func(){setViewPersonGenomeDiscreteTraitRulesPage(window, geneticAnalysisObject, traitName, genomeIdentifier, genomeName, previousPage)}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
title := getPageTitleCentered("View Trait Rules - " + traitName)
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
|
|
|
|
description1 := widget.NewLabel("Below are the trait rule results for this genome.")
|
|
|
|
rulesHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
2024-07-19 19:16:28 +02:00
|
|
|
setDiscreteTraitRulesExplainerPage(window, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
description1Row := container.NewHBox(layout.NewSpacer(), description1, rulesHelpButton, layout.NewSpacer())
|
|
|
|
|
|
|
|
getGenomeNameRow := func()*fyne.Container{
|
|
|
|
|
|
|
|
genomeLabel := widget.NewLabel("Genome:")
|
|
|
|
genomeNameLabel := getBoldLabel(genomeName)
|
|
|
|
|
|
|
|
if (genomeName == "Only Exclude Conflicts" || genomeName == "Only Include Shared"){
|
|
|
|
genomeHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setCombinedGenomesExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
genomeNameRow := container.NewHBox(layout.NewSpacer(), genomeLabel, genomeNameLabel, genomeHelpButton, layout.NewSpacer())
|
|
|
|
return genomeNameRow
|
|
|
|
}
|
|
|
|
genomeNameRow := container.NewHBox(layout.NewSpacer(), genomeLabel, genomeNameLabel, layout.NewSpacer())
|
|
|
|
return genomeNameRow
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeNameRow := getGenomeNameRow()
|
|
|
|
|
|
|
|
traitRulesMap, err := traits.GetTraitRulesMap(traitName)
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
numberOfRulesTested := 0
|
|
|
|
|
|
|
|
rulesList_RulePassed := make([]string, 0)
|
|
|
|
rulesList_RuleNotPassed := make([]string, 0)
|
|
|
|
rulesList_Unknown := make([]string, 0)
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
for ruleIdentifierHex, _ := range traitRulesMap{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
ruleIdentifier, err := encoding.DecodeHexStringTo3ByteArray(ruleIdentifierHex)
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
ruleStatusIsKnown, genomePassesRule, err := readGeneticAnalysis.GetPersonDiscreteTraitRuleInfoFromGeneticAnalysis(geneticAnalysisObject, traitName, ruleIdentifier, genomeIdentifier)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (ruleStatusIsKnown == false){
|
2024-06-02 10:43:39 +02:00
|
|
|
rulesList_Unknown = append(rulesList_Unknown, ruleIdentifierHex)
|
2024-04-11 15:51:56 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
numberOfRulesTested += 1
|
|
|
|
|
|
|
|
if (genomePassesRule == true){
|
2024-06-02 10:43:39 +02:00
|
|
|
rulesList_RulePassed = append(rulesList_RulePassed, ruleIdentifierHex)
|
2024-04-11 15:51:56 +02:00
|
|
|
} else {
|
2024-06-02 10:43:39 +02:00
|
|
|
rulesList_RuleNotPassed = append(rulesList_RuleNotPassed, ruleIdentifierHex)
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
numberOfRulesTestedString := helpers.ConvertIntToString(numberOfRulesTested)
|
|
|
|
|
|
|
|
totalNumberOfRules := len(traitRulesMap)
|
|
|
|
totalNumberOfRulesString := helpers.ConvertIntToString(totalNumberOfRules)
|
|
|
|
|
|
|
|
rulesTestedLabel := widget.NewLabel("Rules Tested:")
|
|
|
|
rulesTestedText := getBoldLabel(numberOfRulesTestedString + "/" + totalNumberOfRulesString)
|
|
|
|
rulesTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
2024-07-19 19:16:28 +02:00
|
|
|
setDiscreteTraitQuantityOfRulesTestedExplainerPage(window, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
rulesTestedRow := container.NewHBox(layout.NewSpacer(), rulesTestedLabel, rulesTestedText, rulesTestedHelpButton, layout.NewSpacer())
|
|
|
|
|
|
|
|
getTraitRulesGrid := func()(*fyne.Container, error){
|
|
|
|
|
|
|
|
ruleIdentifierLabel := getItalicLabelCentered("Rule Identifier")
|
|
|
|
ruleEffectsLabel := getItalicLabelCentered("Rule Effects")
|
|
|
|
genomePassesRuleLabel := getItalicLabelCentered("Genome Passes Rule")
|
|
|
|
emptyLabel := widget.NewLabel("")
|
|
|
|
|
|
|
|
ruleIdentifierColumn := container.NewVBox(ruleIdentifierLabel, widget.NewSeparator())
|
|
|
|
ruleEffectsColumn := container.NewVBox(ruleEffectsLabel, widget.NewSeparator())
|
|
|
|
genomePassesRuleColumn := container.NewVBox(genomePassesRuleLabel, widget.NewSeparator())
|
|
|
|
viewButtonsColumn := container.NewVBox(emptyLabel, widget.NewSeparator())
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
addRuleRow := func(ruleIdentifierHex string)error{
|
|
|
|
|
|
|
|
ruleIdentifierLabel := getBoldLabelCentered(ruleIdentifierHex)
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
ruleIdentifier, err := encoding.DecodeHexStringTo3ByteArray(ruleIdentifierHex)
|
|
|
|
if (err != nil){ return err }
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
ruleStatusIsKnown, genomePassesRule, err := readGeneticAnalysis.GetPersonDiscreteTraitRuleInfoFromGeneticAnalysis(geneticAnalysisObject, traitName, ruleIdentifier, genomeIdentifier)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
getGenomePassesRuleText := func()string{
|
|
|
|
if (ruleStatusIsKnown == false){
|
|
|
|
|
|
|
|
result := translate("Unknown")
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
genomePassesRuleString := helpers.ConvertBoolToYesOrNoString(genomePassesRule)
|
|
|
|
genomePassesRuleTranslated := translate(genomePassesRuleString)
|
|
|
|
|
|
|
|
return genomePassesRuleTranslated
|
|
|
|
}
|
|
|
|
|
|
|
|
genomePassesRuleText := getGenomePassesRuleText()
|
|
|
|
genomePassesRuleLabel := getBoldLabelCentered(genomePassesRuleText)
|
|
|
|
|
|
|
|
// We add all of the columns except for the rule effects column
|
|
|
|
// We do this because the rule effects column may be multiple rows tall
|
|
|
|
|
|
|
|
viewRuleButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
|
2024-07-19 19:16:28 +02:00
|
|
|
setViewPersonGeneticAnalysisDiscreteTraitRuleDetailsPage(window, geneticAnalysisObject, traitName, ruleIdentifier, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
ruleIdentifierColumn.Add(ruleIdentifierLabel)
|
|
|
|
genomePassesRuleColumn.Add(genomePassesRuleLabel)
|
|
|
|
viewButtonsColumn.Add(viewRuleButton)
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
traitRuleObject, exists := traitRulesMap[ruleIdentifierHex]
|
2024-04-11 15:51:56 +02:00
|
|
|
if (exists == false){
|
|
|
|
return errors.New("Trait rule not found after being found already.")
|
|
|
|
}
|
|
|
|
|
|
|
|
ruleOutcomePointsMap := traitRuleObject.OutcomePointsMap
|
|
|
|
|
|
|
|
outcomeNamesList := helpers.GetListOfMapKeys(ruleOutcomePointsMap)
|
|
|
|
|
|
|
|
// We have to sort the outcome names so they always show up in the same order
|
|
|
|
helpers.SortStringListToUnicodeOrder(outcomeNamesList)
|
|
|
|
|
|
|
|
for index, outcomeName := range outcomeNamesList{
|
|
|
|
|
|
|
|
outcomeEffectInt, exists := ruleOutcomePointsMap[outcomeName]
|
|
|
|
if (exists == false){
|
|
|
|
return errors.New("OutcomeName not found in ruleOutcomePointsMap after being found already: " + outcomeName)
|
|
|
|
}
|
|
|
|
|
|
|
|
getOutcomeEffectString := func()string{
|
|
|
|
|
|
|
|
outcomeEffectString := helpers.ConvertIntToString(outcomeEffectInt)
|
|
|
|
|
|
|
|
if (outcomeEffectInt < 0){
|
|
|
|
return outcomeEffectString
|
|
|
|
}
|
|
|
|
outcomeEffect := "+" + outcomeEffectString
|
|
|
|
return outcomeEffect
|
|
|
|
}
|
|
|
|
|
|
|
|
outcomeEffect := getOutcomeEffectString()
|
|
|
|
|
|
|
|
outcomeRow := getBoldLabelCentered(outcomeName + ": " + outcomeEffect)
|
|
|
|
ruleEffectsColumn.Add(outcomeRow)
|
|
|
|
|
|
|
|
if (index > 0){
|
|
|
|
|
|
|
|
emptyLabelA := widget.NewLabel("")
|
|
|
|
emptyLabelB := widget.NewLabel("")
|
|
|
|
emptyLabelC := widget.NewLabel("")
|
|
|
|
|
|
|
|
ruleIdentifierColumn.Add(emptyLabelA)
|
|
|
|
genomePassesRuleColumn.Add(emptyLabelB)
|
|
|
|
viewButtonsColumn.Add(emptyLabelC)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ruleIdentifierColumn.Add(widget.NewSeparator())
|
|
|
|
ruleEffectsColumn.Add(widget.NewSeparator())
|
|
|
|
genomePassesRuleColumn.Add(widget.NewSeparator())
|
|
|
|
viewButtonsColumn.Add(widget.NewSeparator())
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Items within each group are sorted so they will display the same way whenever user refreshes page
|
|
|
|
|
|
|
|
helpers.SortStringListToUnicodeOrder(rulesList_RulePassed)
|
|
|
|
helpers.SortStringListToUnicodeOrder(rulesList_RuleNotPassed)
|
|
|
|
helpers.SortStringListToUnicodeOrder(rulesList_Unknown)
|
|
|
|
|
|
|
|
for _, ruleIdentifier := range rulesList_RulePassed{
|
|
|
|
|
|
|
|
err = addRuleRow(ruleIdentifier)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
}
|
|
|
|
for _, ruleIdentifier := range rulesList_RuleNotPassed{
|
|
|
|
|
|
|
|
err = addRuleRow(ruleIdentifier)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
}
|
|
|
|
for _, ruleIdentifier := range rulesList_Unknown{
|
|
|
|
|
|
|
|
err = addRuleRow(ruleIdentifier)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
}
|
|
|
|
|
|
|
|
ruleEffectsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
2024-07-19 19:16:28 +02:00
|
|
|
setDiscreteTraitRuleOutcomeEffectsExplainerPage(window, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
ruleEffectsColumn.Add(ruleEffectsHelpButton)
|
|
|
|
|
|
|
|
genomePassesRuleHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
2024-07-19 19:16:28 +02:00
|
|
|
setGenomePassesDiscreteTraitRuleExplainerPage(window, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
genomePassesRuleColumn.Add(genomePassesRuleHelpButton)
|
|
|
|
|
|
|
|
traitRulesGrid := container.NewHBox(layout.NewSpacer(), ruleIdentifierColumn, ruleEffectsColumn, genomePassesRuleColumn, viewButtonsColumn, layout.NewSpacer())
|
|
|
|
|
|
|
|
return traitRulesGrid, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
traitRulesGrid, err := getTraitRulesGrid()
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1Row, widget.NewSeparator(), genomeNameRow, widget.NewSeparator(), rulesTestedRow, widget.NewSeparator(), traitRulesGrid)
|
|
|
|
|
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This function provides a page to view the details of a specific trait rule from a person genetic analysis
|
|
|
|
// The page will show the rule details for all of the person's genomes
|
2024-07-19 19:16:28 +02:00
|
|
|
func setViewPersonGeneticAnalysisDiscreteTraitRuleDetailsPage(window fyne.Window, geneticAnalysisObject geneticAnalysis.PersonAnalysis, traitName string, ruleIdentifier [3]byte, previousPage func()){
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
currentPage := func(){setViewPersonGeneticAnalysisDiscreteTraitRuleDetailsPage(window, geneticAnalysisObject, traitName, ruleIdentifier, previousPage)}
|
2024-04-11 15:51:56 +02:00
|
|
|
|
|
|
|
title := getPageTitleCentered("Trait Rule Details - " + traitName)
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
|
|
|
|
description := getLabelCentered("Below is the rule result for the person's genomes.")
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
ruleIdentifierHex := encoding.EncodeBytesToHexString(ruleIdentifier[:])
|
|
|
|
|
2024-04-11 15:51:56 +02:00
|
|
|
ruleIdentifierLabel := widget.NewLabel("Rule Identifier:")
|
2024-06-02 10:43:39 +02:00
|
|
|
ruleIdentifierText := getBoldLabel(ruleIdentifierHex)
|
2024-04-11 15:51:56 +02:00
|
|
|
ruleInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){
|
2024-07-19 19:16:28 +02:00
|
|
|
setViewDiscreteTraitRuleDetailsPage(window, traitName, ruleIdentifierHex, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
ruleIdentifierRow := container.NewHBox(layout.NewSpacer(), ruleIdentifierLabel, ruleIdentifierText, ruleInfoButton, layout.NewSpacer())
|
|
|
|
|
|
|
|
getGenomesRuleInfoGrid := func()(*fyne.Container, error){
|
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, onlyIncludeSharedGenomeIdentifier, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(geneticAnalysisObject)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
genomeNameLabel := getItalicLabelCentered("Genome Name")
|
|
|
|
genomePassesRuleLabel := getItalicLabelCentered("Genome Passes Rule")
|
|
|
|
|
|
|
|
genomeNameColumn := container.NewVBox(genomeNameLabel, widget.NewSeparator())
|
|
|
|
genomePassesRuleColumn := container.NewVBox(genomePassesRuleLabel, widget.NewSeparator())
|
|
|
|
|
2024-06-02 10:43:39 +02:00
|
|
|
addGenomeRow := func(genomeName string, genomeIdentifier [16]byte, isACombinedGenome bool)error{
|
2024-04-11 15:51:56 +02:00
|
|
|
|
2024-07-19 19:16:28 +02:00
|
|
|
genomeRuleStatusKnown, genomePassesRule, err := readGeneticAnalysis.GetPersonDiscreteTraitRuleInfoFromGeneticAnalysis(geneticAnalysisObject, traitName, ruleIdentifier, genomeIdentifier)
|
2024-04-11 15:51:56 +02:00
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
getGenomePassesRuleText := func()string{
|
|
|
|
|
|
|
|
if (genomeRuleStatusKnown == false){
|
|
|
|
result := translate("Unknown")
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
genomePassesRuleString := helpers.ConvertBoolToYesOrNoString(genomePassesRule)
|
|
|
|
|
|
|
|
genomePassesRuleTranslated := translate(genomePassesRuleString)
|
|
|
|
return genomePassesRuleTranslated
|
|
|
|
}
|
|
|
|
|
|
|
|
genomePassesRuleText := getGenomePassesRuleText()
|
|
|
|
|
|
|
|
getGenomeNameCell := func()*fyne.Container{
|
|
|
|
if (isACombinedGenome == false){
|
|
|
|
|
|
|
|
genomeNameLabel := getBoldLabelCentered(genomeName)
|
|
|
|
return genomeNameLabel
|
|
|
|
}
|
|
|
|
viewHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setCombinedGenomesExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
|
|
|
|
genomeNameLabel := getBoldLabel(genomeName)
|
|
|
|
genomeNameCell := container.NewHBox(layout.NewSpacer(), viewHelpButton, genomeNameLabel, layout.NewSpacer())
|
|
|
|
|
|
|
|
return genomeNameCell
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeNameCell := getGenomeNameCell()
|
|
|
|
genomeNameColumn.Add(genomeNameCell)
|
|
|
|
|
|
|
|
genomePassesRuleLabel := getBoldLabelCentered(genomePassesRuleText)
|
|
|
|
genomePassesRuleColumn.Add(genomePassesRuleLabel)
|
|
|
|
|
|
|
|
genomeNameColumn.Add(widget.NewSeparator())
|
|
|
|
genomePassesRuleColumn.Add(widget.NewSeparator())
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
|
|
|
|
err := addGenomeRow("Only Exclude Conflicts", onlyExcludeConflictsGenomeIdentifier, true)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
err = addGenomeRow("Only Include Shared", onlyIncludeSharedGenomeIdentifier, true)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, genomeIdentifier := range allRawGenomeIdentifiersList{
|
|
|
|
|
|
|
|
getGenomeName := func()(string, error){
|
|
|
|
|
|
|
|
genomeFound, _, timeGenomeWasExported, _, _, _, companyName, _, _, err := myGenomes.GetMyRawGenomeMetadata(genomeIdentifier)
|
|
|
|
if (err != nil) { return "", err }
|
|
|
|
if (genomeFound == false){
|
2024-06-02 10:43:39 +02:00
|
|
|
return "", errors.New("MyGenomeInfo for genome from analysisObject not found.")
|
2024-04-11 15:51:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (multipleGenomesExist == false){
|
|
|
|
return companyName, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// We show the date that the genome was exported
|
|
|
|
|
|
|
|
exportTimeAgo, err := helpers.ConvertUnixTimeToTimeAgoTranslated(timeGenomeWasExported, false)
|
|
|
|
if (err != nil){ return "", err }
|
|
|
|
|
|
|
|
genomeName := companyName + " (Exported " + exportTimeAgo + ")"
|
|
|
|
|
|
|
|
return genomeName, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeName, err := getGenomeName()
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
err = addGenomeRow(genomeName, genomeIdentifier, false)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
}
|
|
|
|
|
|
|
|
genomePassesRuleHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
2024-07-19 19:16:28 +02:00
|
|
|
setGenomePassesDiscreteTraitRuleExplainerPage(window, currentPage)
|
2024-04-11 15:51:56 +02:00
|
|
|
})
|
|
|
|
genomePassesRuleColumn.Add(genomePassesRuleHelpButton)
|
|
|
|
|
|
|
|
genomesContainer := container.NewHBox(layout.NewSpacer(), genomeNameColumn, genomePassesRuleColumn, layout.NewSpacer())
|
|
|
|
|
|
|
|
return genomesContainer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genomesRuleInfoGrid, err := getGenomesRuleInfoGrid()
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), ruleIdentifierRow, widget.NewSeparator(), genomesRuleInfoGrid)
|
|
|
|
|
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-08-09 16:23:37 +02:00
|
|
|
func setViewPersonGeneticAnalysisNumericTraitsPage(window fyne.Window, personIdentifier string, analysisObject geneticAnalysis.PersonAnalysis, previousPage func()){
|
|
|
|
|
|
|
|
currentPage := func(){setViewPersonGeneticAnalysisNumericTraitsPage(window, personIdentifier, analysisObject, previousPage)}
|
|
|
|
|
|
|
|
title := getPageTitleCentered("Viewing Genetic Analysis - Numeric Traits")
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
|
|
|
|
description := getLabelCentered("Below is an analysis of the numeric traits for this person's genome.")
|
|
|
|
|
|
|
|
getTraitsContainer := func()(*fyne.Container, error){
|
|
|
|
|
|
|
|
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, _, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(analysisObject)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
// Outputs:
|
|
|
|
// -[16]byte: Main genome identifier (Is either the combined Only exclude conflicts genome or the only genome)
|
|
|
|
// -error
|
|
|
|
getMainGenomeIdentifier := func()([16]byte, error){
|
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
return onlyExcludeConflictsGenomeIdentifier, nil
|
|
|
|
}
|
|
|
|
// Only 1 genome exists
|
|
|
|
|
|
|
|
genomeIdentifier := allRawGenomeIdentifiersList[0]
|
|
|
|
|
|
|
|
return genomeIdentifier, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
mainGenomeIdentifier, err := getMainGenomeIdentifier()
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
traitNameLabel := getItalicLabelCentered("Trait Name")
|
|
|
|
|
|
|
|
predictedOutcomeLabel := getItalicLabelCentered("Predicted Outcome")
|
|
|
|
|
|
|
|
confidenceRangeLabel := getItalicLabelCentered("Confidence Range")
|
|
|
|
|
|
|
|
conflictExistsLabel := getItalicLabelCentered("Conflict Exists?")
|
|
|
|
|
|
|
|
emptyLabel5 := widget.NewLabel("")
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
traitNameColumn := container.NewVBox(traitNameLabel, widget.NewSeparator())
|
|
|
|
predictedOutcomeColumn := container.NewVBox(predictedOutcomeLabel, widget.NewSeparator())
|
|
|
|
confidenceRangeColumn := container.NewVBox(confidenceRangeLabel, widget.NewSeparator())
|
|
|
|
conflictExistsColumn := container.NewVBox(conflictExistsLabel, widget.NewSeparator())
|
|
|
|
viewButtonsColumn := container.NewVBox(emptyLabel5, widget.NewSeparator())
|
2024-08-09 16:23:37 +02:00
|
|
|
|
|
|
|
traitObjectsList, err := traits.GetTraitObjectsList()
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
for _, traitObject := range traitObjectsList{
|
|
|
|
|
|
|
|
traitIsDiscreteOrNumeric := traitObject.DiscreteOrNumeric
|
|
|
|
if (traitIsDiscreteOrNumeric != "Numeric"){
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
traitName := traitObject.TraitName
|
|
|
|
traitLociList := traitObject.LociList
|
|
|
|
|
|
|
|
if (len(traitLociList) == 0){
|
|
|
|
// This trait does not have any loci to analyze
|
|
|
|
// We cannot analyze it yet
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
traitNameText := getBoldLabelCentered(traitName)
|
|
|
|
|
2024-08-15 14:14:23 +02:00
|
|
|
neuralNetworkExists := trainedPredictionModels.CheckIfAttributeNeuralNetworkExists(traitName)
|
2024-08-09 16:23:37 +02:00
|
|
|
if (neuralNetworkExists == false){
|
|
|
|
// This trait has no neural network
|
|
|
|
// We cannot analyze it
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
analysisExists, predictedOutcome, confidenceRangesMap, _, _, conflictExists, err := readGeneticAnalysis.GetPersonNumericTraitInfoFromGeneticAnalysis(analysisObject, traitName, mainGenomeIdentifier)
|
2024-08-09 16:23:37 +02:00
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
outcomeFormatter := traitObject.NumericValueFormatter
|
|
|
|
|
|
|
|
getPredictionLabel := func()(fyne.Widget, error){
|
2024-08-09 16:23:37 +02:00
|
|
|
|
|
|
|
if (analysisExists == false){
|
|
|
|
result := getItalicLabel("Unknown")
|
2024-08-13 15:25:47 +02:00
|
|
|
return result, nil
|
2024-08-09 16:23:37 +02:00
|
|
|
}
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
predictedOutcomeString, err := outcomeFormatter(predictedOutcome, true)
|
|
|
|
if (err != nil) { return nil, err }
|
2024-08-09 16:23:37 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
result := getBoldLabel(predictedOutcomeString)
|
2024-08-09 16:23:37 +02:00
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
return result, nil
|
2024-08-09 16:23:37 +02:00
|
|
|
}
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
predictionLabel, err := getPredictionLabel()
|
|
|
|
if (err != nil) { return nil, err }
|
2024-08-09 16:23:37 +02:00
|
|
|
|
|
|
|
predictionLabelCentered := getWidgetCentered(predictionLabel)
|
|
|
|
|
|
|
|
getConfidenceRangeLabel := func()(fyne.Widget, error){
|
|
|
|
|
|
|
|
if (analysisExists == false){
|
|
|
|
unknownLabel := widget.NewLabel("Unknown")
|
|
|
|
return unknownLabel, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is a list of the percentage accuracies in the map
|
|
|
|
// For example: 80% == The distance from the prediction you must travel for 80% of the predictions to be
|
|
|
|
// accurate within that range
|
|
|
|
confidenceRangePercentagesList := helpers.GetListOfMapKeys(confidenceRangesMap)
|
|
|
|
|
|
|
|
// We sort the list so the percentage is always the same upon refreshing the page
|
|
|
|
slices.Sort(confidenceRangePercentagesList)
|
|
|
|
|
|
|
|
closestToEightyPercentage, err := helpers.GetClosestIntInList(confidenceRangePercentagesList, 80)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
closestToEightyPercentageConfidenceDistance, exists := confidenceRangesMap[closestToEightyPercentage]
|
|
|
|
if (exists == false){
|
|
|
|
return nil, errors.New("GetListOfMapKeys returning list of elements which contains element which is not in the map.")
|
|
|
|
}
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
closestConfidenceDistanceString, err := outcomeFormatter(closestToEightyPercentageConfidenceDistance, false)
|
|
|
|
if (err != nil) { return nil, err }
|
2024-08-09 16:23:37 +02:00
|
|
|
|
|
|
|
closestToEightyPercentageString := helpers.ConvertIntToString(closestToEightyPercentage)
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
confidenceRangeLabelValueFormatted := "+/- " + closestConfidenceDistanceString + " (" + closestToEightyPercentageString + "%)"
|
2024-08-09 16:23:37 +02:00
|
|
|
|
|
|
|
confidenceRangeLabel := getBoldLabel(confidenceRangeLabelValueFormatted)
|
|
|
|
|
|
|
|
return confidenceRangeLabel, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
confidenceRangeLabel, err := getConfidenceRangeLabel()
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
confidenceRangeLabelCentered := getWidgetCentered(confidenceRangeLabel)
|
|
|
|
|
|
|
|
conflictExistsString := helpers.ConvertBoolToYesOrNoString(conflictExists)
|
|
|
|
conflictExistsLabel := getBoldLabelCentered(conflictExistsString)
|
|
|
|
|
|
|
|
viewDetailsButton := getWidgetCentered(widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
|
2024-08-13 15:25:47 +02:00
|
|
|
setViewPersonGeneticAnalysisNumericTraitDetailsPage(window, personIdentifier, analysisObject, traitName, currentPage)
|
2024-08-09 16:23:37 +02:00
|
|
|
}))
|
|
|
|
|
|
|
|
traitNameColumn.Add(traitNameText)
|
|
|
|
predictedOutcomeColumn.Add(predictionLabelCentered)
|
|
|
|
confidenceRangeColumn.Add(confidenceRangeLabelCentered)
|
|
|
|
conflictExistsColumn.Add(conflictExistsLabel)
|
|
|
|
viewButtonsColumn.Add(viewDetailsButton)
|
|
|
|
|
|
|
|
traitNameColumn.Add(widget.NewSeparator())
|
|
|
|
predictedOutcomeColumn.Add(widget.NewSeparator())
|
|
|
|
confidenceRangeColumn.Add(widget.NewSeparator())
|
|
|
|
conflictExistsColumn.Add(widget.NewSeparator())
|
|
|
|
viewButtonsColumn.Add(widget.NewSeparator())
|
|
|
|
}
|
|
|
|
|
|
|
|
predictedOutcomeHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
//TODO
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
})
|
|
|
|
predictedOutcomeColumn.Add(predictedOutcomeHelpButton)
|
|
|
|
|
|
|
|
confidenceRangeHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
//TODO
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
})
|
|
|
|
confidenceRangeColumn.Add(confidenceRangeHelpButton)
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
traitsContainer := container.NewHBox(layout.NewSpacer(), traitNameColumn, predictedOutcomeColumn, confidenceRangeColumn)
|
2024-08-09 16:23:37 +02:00
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
|
|
|
|
conflictExistsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setPersonGeneticAnalysisConflictExistsExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
|
|
|
|
conflictExistsColumn.Add(conflictExistsHelpButton)
|
|
|
|
traitsContainer.Add(conflictExistsColumn)
|
|
|
|
}
|
|
|
|
|
|
|
|
traitsContainer.Add(viewButtonsColumn)
|
|
|
|
traitsContainer.Add(layout.NewSpacer())
|
|
|
|
|
|
|
|
return traitsContainer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
traitsContainer, err := getTraitsContainer()
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), traitsContainer)
|
|
|
|
|
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-08-13 15:25:47 +02:00
|
|
|
|
|
|
|
func setViewPersonGeneticAnalysisNumericTraitDetailsPage(window fyne.Window, personIdentifier string, analysisObject geneticAnalysis.PersonAnalysis, traitName string, previousPage func()){
|
|
|
|
|
|
|
|
currentPage := func(){setViewPersonGeneticAnalysisNumericTraitDetailsPage(window, personIdentifier, analysisObject, traitName, previousPage)}
|
|
|
|
|
|
|
|
title := getPageTitleCentered("Viewing Genetic Analysis - " + traitName)
|
|
|
|
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
|
|
|
|
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, onlyIncludeSharedGenomeIdentifier, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(analysisObject)
|
|
|
|
if (err != nil) {
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
getDescriptionSection := func()*fyne.Container{
|
|
|
|
|
|
|
|
if (multipleGenomesExist == false){
|
|
|
|
description := getLabelCentered("Below is the trait information for this person's genome.")
|
|
|
|
|
|
|
|
return description
|
|
|
|
}
|
|
|
|
|
|
|
|
description1 := getLabelCentered("Below is the trait information for this person's genomes.")
|
|
|
|
description2 := getLabelCentered("The first two genomes are created by combining multiple genomes.")
|
|
|
|
|
|
|
|
descriptionsSection := container.NewVBox(description1, description2)
|
|
|
|
|
|
|
|
return descriptionsSection
|
|
|
|
}
|
|
|
|
|
|
|
|
descriptionSection := getDescriptionSection()
|
|
|
|
|
|
|
|
traitNameLabel := widget.NewLabel("Trait:")
|
|
|
|
traitNameText := getBoldLabel(traitName)
|
|
|
|
traitInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){
|
|
|
|
setViewTraitDetailsPage(window, traitName, currentPage)
|
|
|
|
})
|
|
|
|
traitNameRow := container.NewHBox(layout.NewSpacer(), traitNameLabel, traitNameText, traitInfoButton, layout.NewSpacer())
|
|
|
|
|
|
|
|
getGenomesContainer := func()(*fyne.Container, error){
|
|
|
|
|
|
|
|
traitObject, err := traits.GetTraitObject(traitName)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
traitIsDiscreteOrNumeric := traitObject.DiscreteOrNumeric
|
|
|
|
if (traitIsDiscreteOrNumeric != "Numeric"){
|
|
|
|
return nil, errors.New("setViewPersonGeneticAnalysisNumericTraitDetailsPage called with non-numeric trait: " + traitName)
|
|
|
|
}
|
|
|
|
|
|
|
|
traitLociList := traitObject.LociList
|
|
|
|
|
|
|
|
totalQuantityOfLoci := len(traitLociList)
|
|
|
|
totalQuantityOfLociString := helpers.ConvertIntToString(totalQuantityOfLoci)
|
|
|
|
|
|
|
|
emptyLabel1 := widget.NewLabel("")
|
|
|
|
genomeNameLabel := getItalicLabelCentered("Genome Name")
|
|
|
|
|
|
|
|
emptyLabel2 := widget.NewLabel("")
|
|
|
|
predictedOutcomeLabel := getItalicLabelCentered("Predicted Outcome")
|
|
|
|
|
|
|
|
emptyLabel3 := widget.NewLabel("")
|
|
|
|
predictionConfidenceLabel := getItalicLabelCentered("Confidence Range")
|
|
|
|
|
|
|
|
quantityOfLabel := getItalicLabelCentered("Quantity of")
|
|
|
|
lociKnownLabel := getItalicLabelCentered("Loci Known")
|
|
|
|
|
|
|
|
emptyLabel4 := widget.NewLabel("")
|
|
|
|
emptyLabel5 := widget.NewLabel("")
|
|
|
|
|
|
|
|
genomeNameColumn := container.NewVBox(emptyLabel1, genomeNameLabel, widget.NewSeparator())
|
|
|
|
predictedOutcomeColumn := container.NewVBox(emptyLabel2, predictedOutcomeLabel, widget.NewSeparator())
|
|
|
|
predictionConfidenceColumn := container.NewVBox(emptyLabel3, predictionConfidenceLabel, widget.NewSeparator())
|
|
|
|
quantityOfLociKnownColumn := container.NewVBox(quantityOfLabel, lociKnownLabel, widget.NewSeparator())
|
|
|
|
viewDetailsButtonsColumn := container.NewVBox(emptyLabel4, emptyLabel5, widget.NewSeparator())
|
|
|
|
|
|
|
|
addGenomeRow := func(genomeName string, genomeIdentifier [16]byte, isACombinedGenome bool)error{
|
|
|
|
|
|
|
|
getGenomeNameCell := func()*fyne.Container{
|
|
|
|
if (isACombinedGenome == false){
|
|
|
|
|
|
|
|
genomeNameLabel := getBoldLabelCentered(genomeName)
|
|
|
|
return genomeNameLabel
|
|
|
|
}
|
|
|
|
viewHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
setCombinedGenomesExplainerPage(window, currentPage)
|
|
|
|
})
|
|
|
|
|
|
|
|
genomeNameLabel := getBoldLabel(genomeName)
|
|
|
|
genomeNameCell := container.NewHBox(layout.NewSpacer(), viewHelpButton, genomeNameLabel, layout.NewSpacer())
|
|
|
|
|
|
|
|
return genomeNameCell
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeNameCell := getGenomeNameCell()
|
|
|
|
|
|
|
|
analysisExists, predictedOutcome, predictionConfidenceRangesMap, quantityOfLociKnown, _, _, err := readGeneticAnalysis.GetPersonNumericTraitInfoFromGeneticAnalysis(analysisObject, traitName, genomeIdentifier)
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
outcomeFormatter := traitObject.NumericValueFormatter
|
|
|
|
|
|
|
|
getPredictedOutcomeLabel := func()(fyne.Widget, error){
|
|
|
|
|
|
|
|
if (analysisExists == false){
|
|
|
|
|
|
|
|
result := widget.NewLabel(translate("Unknown"))
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
outcomeFormatted, err := outcomeFormatter(predictedOutcome, true)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
outcomeLabel := getBoldLabel(outcomeFormatted)
|
|
|
|
|
|
|
|
return outcomeLabel, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
predictedOutcomeLabel, err := getPredictedOutcomeLabel()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
predictedOutcomeLabelCentered := getWidgetCentered(predictedOutcomeLabel)
|
|
|
|
|
|
|
|
getConfidenceRangeLabel := func()(fyne.Widget, error){
|
|
|
|
|
|
|
|
if (analysisExists == false){
|
|
|
|
unknownLabel := widget.NewLabel("Unknown")
|
|
|
|
return unknownLabel, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is a list of the percentage accuracies in the map
|
|
|
|
// For example: 80% == The distance from the prediction you must travel for 80% of the predictions to be
|
|
|
|
// accurate within that range
|
|
|
|
confidenceRangePercentagesList := helpers.GetListOfMapKeys(predictionConfidenceRangesMap)
|
|
|
|
|
|
|
|
// We sort the list so the percentage is always the same upon refreshing the page
|
|
|
|
slices.Sort(confidenceRangePercentagesList)
|
|
|
|
|
|
|
|
closestToEightyPercentage, err := helpers.GetClosestIntInList(confidenceRangePercentagesList, 80)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
closestToEightyPercentageConfidenceDistance, exists := predictionConfidenceRangesMap[closestToEightyPercentage]
|
|
|
|
if (exists == false){
|
|
|
|
return nil, errors.New("GetListOfMapKeys returning list of elements which contains element which is not in the map.")
|
|
|
|
}
|
|
|
|
|
|
|
|
closestConfidenceDistanceString, err := outcomeFormatter(closestToEightyPercentageConfidenceDistance, false)
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
closestToEightyPercentageString := helpers.ConvertIntToString(closestToEightyPercentage)
|
|
|
|
|
|
|
|
confidenceRangeLabelValueFormatted := "+/- " + closestConfidenceDistanceString + " (" + closestToEightyPercentageString + "%)"
|
|
|
|
|
|
|
|
confidenceRangeLabel := getBoldLabel(confidenceRangeLabelValueFormatted)
|
|
|
|
|
|
|
|
return confidenceRangeLabel, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
confidenceRangeLabel, err := getConfidenceRangeLabel()
|
|
|
|
if (err != nil) { return err }
|
|
|
|
|
|
|
|
confidenceRangeLabelCentered := getWidgetCentered(confidenceRangeLabel)
|
|
|
|
|
|
|
|
genomeQuantityOfLociKnownString := helpers.ConvertIntToString(quantityOfLociKnown)
|
|
|
|
quantityOfLociKnownLabel := getBoldLabelCentered(genomeQuantityOfLociKnownString + "/" + totalQuantityOfLociString)
|
|
|
|
|
|
|
|
viewDetailsButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
|
|
|
|
//TODO
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
})
|
|
|
|
|
|
|
|
genomeNameColumn.Add(genomeNameCell)
|
|
|
|
predictedOutcomeColumn.Add(predictedOutcomeLabelCentered)
|
|
|
|
predictionConfidenceColumn.Add(confidenceRangeLabelCentered)
|
|
|
|
quantityOfLociKnownColumn.Add(quantityOfLociKnownLabel)
|
|
|
|
viewDetailsButtonsColumn.Add(viewDetailsButton)
|
|
|
|
|
|
|
|
genomeNameColumn.Add(widget.NewSeparator())
|
|
|
|
predictedOutcomeColumn.Add(widget.NewSeparator())
|
|
|
|
predictionConfidenceColumn.Add(widget.NewSeparator())
|
|
|
|
quantityOfLociKnownColumn.Add(widget.NewSeparator())
|
|
|
|
viewDetailsButtonsColumn.Add(widget.NewSeparator())
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if (multipleGenomesExist == true){
|
|
|
|
|
|
|
|
err := addGenomeRow("Only Exclude Conflicts", onlyExcludeConflictsGenomeIdentifier, true)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
|
|
|
|
err = addGenomeRow("Only Include Shared", onlyIncludeSharedGenomeIdentifier, true)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, genomeIdentifier := range allRawGenomeIdentifiersList{
|
|
|
|
|
|
|
|
getGenomeName := func()(string, error){
|
|
|
|
genomeFound, _, timeGenomeWasExported, _, _, _, companyName, _, _, err := myGenomes.GetMyRawGenomeMetadata(genomeIdentifier)
|
|
|
|
if (err != nil) { return "", err }
|
|
|
|
if (genomeFound == false){
|
|
|
|
return "", errors.New("MyGenomeInfo for genome from analysisObject not found.")
|
|
|
|
}
|
|
|
|
|
|
|
|
if (multipleGenomesExist == false){
|
|
|
|
return companyName, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// We show the date the genome was exported
|
|
|
|
|
|
|
|
exportTimeAgo, err := helpers.ConvertUnixTimeToTimeAgoTranslated(timeGenomeWasExported, false)
|
|
|
|
if (err != nil){ return "", err }
|
|
|
|
|
|
|
|
genomeName := companyName + " (Exported " + exportTimeAgo + ")"
|
|
|
|
|
|
|
|
return genomeName, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genomeName, err := getGenomeName()
|
|
|
|
if (err != nil) { return nil, err }
|
|
|
|
|
|
|
|
err = addGenomeRow(genomeName, genomeIdentifier, false)
|
|
|
|
if (err != nil){ return nil, err }
|
|
|
|
}
|
|
|
|
|
|
|
|
predictedOutcomeHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
//TODO
|
|
|
|
})
|
|
|
|
predictedOutcomeColumn.Add(predictedOutcomeHelpButton)
|
|
|
|
|
|
|
|
predictionConfidenceHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
})
|
|
|
|
predictionConfidenceColumn.Add(predictionConfidenceHelpButton)
|
|
|
|
|
|
|
|
quantityOfLociKnownHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
|
|
//TODO
|
|
|
|
showUnderConstructionDialog(window)
|
|
|
|
})
|
|
|
|
quantityOfLociKnownColumn.Add(quantityOfLociKnownHelpButton)
|
|
|
|
|
|
|
|
genomesContainer := container.NewHBox(layout.NewSpacer(), genomeNameColumn, predictedOutcomeColumn, predictionConfidenceColumn, quantityOfLociKnownColumn, viewDetailsButtonsColumn, layout.NewSpacer())
|
|
|
|
|
|
|
|
return genomesContainer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
genomesContainer, err := getGenomesContainer()
|
|
|
|
if (err != nil){
|
|
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), descriptionSection, widget.NewSeparator(), traitNameRow, widget.NewSeparator(), genomesContainer)
|
|
|
|
|
|
|
|
setPageContent(page, window)
|
|
|
|
}
|
|
|
|
|
|
|
|
|