seekia/gui/viewAnalysisGui_Person.go

2674 lines
98 KiB
Go

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"
import "seekia/resources/geneticPredictionModels"
import "seekia/resources/geneticReferences/monogenicDiseases"
import "seekia/resources/geneticReferences/polygenicDiseases"
import "seekia/resources/geneticReferences/traits"
import "seekia/internal/appMemory"
import "seekia/internal/encoding"
import "seekia/internal/genetics/geneticAnalysis"
import "seekia/internal/genetics/myGenomes"
import "seekia/internal/genetics/myPeople"
import "seekia/internal/genetics/readGeneticAnalysis"
import "seekia/internal/helpers"
import "errors"
func setViewPersonGeneticAnalysisPage(window fyne.Window, personIdentifier string, analysisObject geneticAnalysis.PersonAnalysis, numberOfGenomesAnalyzed int, previousPage func()){
appMemory.SetMemoryEntry("CurrentViewedPage", "ViewGeneticAnalysisPage")
currentPage := func(){setViewPersonGeneticAnalysisPage(window, personIdentifier, analysisObject, numberOfGenomesAnalyzed, previousPage)}
title := getPageTitleCentered("Viewing Genetic Analysis")
backButton := getBackButtonCentered(previousPage)
warningLabel1 := getBoldLabelCentered("WARNING: Results are not accurate!")
warningLabel2 := getBoldLabelCentered("The analysis algorithms have known issues that are being worked on.")
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(){
setViewPersonGeneticAnalysisMonogenicDiseasesPage(window, analysisObject, currentPage)
})
polygenicDiseasesButton := widget.NewButton("Polygenic Diseases", func(){
setViewPersonGeneticAnalysisPolygenicDiseasesPage(window, personIdentifier, analysisObject, currentPage)
})
discreteTraitsButton := widget.NewButton("Discrete Traits", func(){
setViewPersonGeneticAnalysisDiscreteTraitsPage(window, personIdentifier, analysisObject, currentPage)
})
numericTraitsButton := widget.NewButton("Numeric Traits", func(){
//TODO
showUnderConstructionDialog(window)
})
categoryButtonsGrid := getContainerCentered(container.NewGridWithColumns(1, generalButton, monogenicDiseasesButton, polygenicDiseasesButton, discreteTraitsButton, numericTraitsButton))
page := container.NewVBox(title, backButton, widget.NewSeparator(), warningLabel1, warningLabel2, widget.NewSeparator(), personNameRow, numberOfAnalyzedGenomesRow, widget.NewSeparator(), categoryButtonsGrid)
setPageContent(page, window)
}
func setViewPersonGeneticAnalysisMonogenicDiseasesPage(window fyne.Window, analysisObject geneticAnalysis.PersonAnalysis, previousPage func()){
currentPage := func(){setViewPersonGeneticAnalysisMonogenicDiseasesPage(window, analysisObject, previousPage)}
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){
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 }
diseaseNameLabel := getItalicLabelCentered("Disease Name")
emptyLabelA := widget.NewLabel("")
personLabel := getItalicLabelCentered("Person")
hasDiseaseLabel := getItalicLabelCentered("Has Disease")
probabilityOfLabel := getItalicLabelCentered("Probability of")
passingVariantLabel := getItalicLabelCentered("Passing Variant")
emptyLabelB := widget.NewLabel("")
conflictExistsLabel := getItalicLabelCentered("Conflict Exists?")
emptyLabelC := widget.NewLabel("")
emptyLabelD := widget.NewLabel("")
diseaseNameColumn := container.NewVBox(emptyLabelA, diseaseNameLabel, widget.NewSeparator())
personHasDiseaseColumn := container.NewVBox(personLabel, hasDiseaseLabel, widget.NewSeparator())
probabilityOfPassingVariantColumn := container.NewVBox(probabilityOfLabel, passingVariantLabel, widget.NewSeparator())
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{
diseaseInfoIsKnown, personHasDisease, _, probabilityOfPassingAVariantFormatted, _, _, _, conflictExistsBool, err := readGeneticAnalysis.GetPersonMonogenicDiseaseInfoFromGeneticAnalysis(analysisObject, diseaseName, mainGenomeIdentifier)
if (err != nil) { return nil, err }
getPersonHasDiseaseText := func()string{
if (diseaseInfoIsKnown == false){
result := translate("Unknown")
return result
}
personHasDiseaseString := helpers.ConvertBoolToYesOrNoString(personHasDisease)
return personHasDiseaseString
}
personHasDiseaseText := getPersonHasDiseaseText()
getProbabilityOfPassingAVariantText := func()string{
if (diseaseInfoIsKnown == false){
result := translate("Unknown")
return result
}
return probabilityOfPassingAVariantFormatted
}
probabilityOfPassingAVariantText := getProbabilityOfPassingAVariantText()
diseaseNameText := getBoldLabelCentered(diseaseName)
diseaseNameColumn.Add(diseaseNameText)
personHasDiseaseLabel := getBoldLabelCentered(personHasDiseaseText)
personHasDiseaseColumn.Add(personHasDiseaseLabel)
probabilityOfPassingVariantLabel := getBoldLabelCentered(probabilityOfPassingAVariantText)
probabilityOfPassingVariantColumn.Add(probabilityOfPassingVariantLabel)
conflictExistsString := helpers.ConvertBoolToYesOrNoString(conflictExistsBool)
conflictExistsLabel := getBoldLabelCentered(conflictExistsString)
conflictExistsColumn.Add(conflictExistsLabel)
viewDetailsButton := getWidgetCentered(widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
setViewPersonGeneticAnalysisMonogenicDiseaseDetailsPage(window, analysisObject, diseaseName, currentPage)
}))
viewButtonsColumn.Add(viewDetailsButton)
diseaseNameColumn.Add(widget.NewSeparator())
personHasDiseaseColumn.Add(widget.NewSeparator())
probabilityOfPassingVariantColumn.Add(widget.NewSeparator())
conflictExistsColumn.Add(widget.NewSeparator())
viewButtonsColumn.Add(widget.NewSeparator())
}
personHasDiseaseHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setPersonHasMonogenicDiseaseExplainerPage(window, currentPage)
})
personHasDiseaseColumn.Add(personHasDiseaseHelpButton)
probabilityOfPassingVariantHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setPersonProbabilityOfPassingVariantExplainerPage(window, currentPage)
})
probabilityOfPassingVariantColumn.Add(probabilityOfPassingVariantHelpButton)
diseasesContainer := container.NewHBox(layout.NewSpacer(), diseaseNameColumn, personHasDiseaseColumn, probabilityOfPassingVariantColumn)
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)
}
func setViewPersonGeneticAnalysisMonogenicDiseaseDetailsPage(window fyne.Window, analysisObject geneticAnalysis.PersonAnalysis, diseaseName string, previousPage func()){
currentPage := func(){setViewPersonGeneticAnalysisMonogenicDiseaseDetailsPage(window, analysisObject, diseaseName, previousPage)}
title := getPageTitleCentered("Viewing Genetic Analysis - " + diseaseName)
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 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){
diseaseVariantsMap, err := monogenicDiseases.GetMonogenicDiseaseVariantsMap(diseaseName)
if (err != nil){ return nil, err }
totalNumberOfVariants := len(diseaseVariantsMap)
totalNumberOfVariantsString := helpers.ConvertIntToString(totalNumberOfVariants)
emptyLabelA := widget.NewLabel("")
genomeNameLabel := getItalicLabelCentered("Genome Name")
personLabel := getItalicLabelCentered("Person")
hasDiseaseLabel := getItalicLabelCentered("Has Disease")
probabilityOfLabel := getItalicLabelCentered("Probability of")
passingVariantLabel := getItalicLabelCentered("Passing Variant")
numberOfLabel1 := getItalicLabelCentered("Number of")
variantsTestedLabel := getItalicLabelCentered("Variants Tested")
numberOfLabel2 := getItalicLabelCentered("Number of")
phasedLociLabel := getItalicLabelCentered("Phased Loci")
emptyLabelB := widget.NewLabel("")
emptyLabelC := widget.NewLabel("")
genomeNameColumn := container.NewVBox(emptyLabelA, genomeNameLabel, widget.NewSeparator())
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())
viewButtonsColumn := container.NewVBox(emptyLabelB, emptyLabelC, widget.NewSeparator())
addGenomeRow := func(genomeName string, genomeIdentifier [16]byte, isACombinedGenome bool)error{
diseaseInfoIsKnown, personHasDisease, _, probabilityOfPassingAVariantFormatted, numberOfVariantsTested, numberOfLociTested, numberOfPhasedLoci, _, err := readGeneticAnalysis.GetPersonMonogenicDiseaseInfoFromGeneticAnalysis(analysisObject, diseaseName, genomeIdentifier)
if (err != nil) { return err }
getPersonHasDiseaseText := func()string{
if (diseaseInfoIsKnown == false){
result := translate("Unknown")
return result
}
personHasDiseaseString := helpers.ConvertBoolToYesOrNoString(personHasDisease)
return personHasDiseaseString
}
personHasDiseaseText := getPersonHasDiseaseText()
getProbabilityOfPassingAVariantText := func()string{
if (diseaseInfoIsKnown == false){
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)
personHasDiseaseLabel := getBoldLabelCentered(personHasDiseaseText)
personHasDiseaseColumn.Add(personHasDiseaseLabel)
probabilityOfPassingAVariantLabel := getBoldLabelCentered(probabilityOfPassingAVariantText)
probabilityOfPassingAVariantColumn.Add(probabilityOfPassingAVariantLabel)
numberOfVariantsTestedString := helpers.ConvertIntToString(numberOfVariantsTested)
numberOfVariantsTestedFormatted := numberOfVariantsTestedString + "/" + totalNumberOfVariantsString
numberOfVariantsTestedLabel := getBoldLabelCentered(numberOfVariantsTestedFormatted)
numberOfVariantsTestedColumn.Add(numberOfVariantsTestedLabel)
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)
})
viewButtonsColumn.Add(viewButton)
genomeNameColumn.Add(widget.NewSeparator())
personHasDiseaseColumn.Add(widget.NewSeparator())
probabilityOfPassingAVariantColumn.Add(widget.NewSeparator())
numberOfVariantsTestedColumn.Add(widget.NewSeparator())
numberOfPhasedLociColumn.Add(widget.NewSeparator())
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){
return "", errors.New("MyGenomeInfo for genome from analysisObject not found.")
}
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 }
}
personHasDiseaseHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setPersonHasMonogenicDiseaseExplainerPage(window, currentPage)
})
personHasDiseaseColumn.Add(personHasDiseaseHelpButton)
probabilityOfPassingAVariantHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setPersonProbabilityOfPassingVariantExplainerPage(window, currentPage)
})
probabilityOfPassingAVariantColumn.Add(probabilityOfPassingAVariantHelpButton)
numberOfVariantsTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setNumberOfTestedVariantsExplainerPage(window, currentPage)
})
numberOfVariantsTestedColumn.Add(numberOfVariantsTestedHelpButton)
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())
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)
setPageContent(page, window)
}
// This page is used to view the person's variants for a particular genome
func setViewPersonGenomeMonogenicDiseaseVariantsPage(window fyne.Window, geneticAnalysisObject geneticAnalysis.PersonAnalysis, genomeIdentifier [16]byte, genomeName string, diseaseName string, previousPage func()){
setLoadingScreen(window, "Loading Disease Variants", "Loading disease variants...")
currentPage := func(){setViewPersonGenomeMonogenicDiseaseVariantsPage(window, geneticAnalysisObject, genomeIdentifier, genomeName, diseaseName, previousPage)}
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()
_, _, _, _, numberOfVariantsTested, numberOfLociTested, numberOfPhasedLoci, _, err := readGeneticAnalysis.GetPersonMonogenicDiseaseInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, genomeIdentifier)
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())
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())
//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())
addVariantRow := func(variantIdentifierHex string)error{
variantObject, exists := diseaseVariantsMap[variantIdentifierHex]
if (exists == false) {
return errors.New("Cannot add variantRow: diseaseVariantsMap missing variant.")
}
variantName := variantObject.VariantNames[0]
variantIdentifier, err := encoding.DecodeHexStringTo3ByteArray(variantIdentifierHex)
if (err != nil) { return err }
numberOfMutationsIsKnown, genomeNumberOfMutations, err := readGeneticAnalysis.GetPersonMonogenicDiseaseVariantInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, variantIdentifier, genomeIdentifier)
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(){
setViewPersonGeneticAnalysisMonogenicDiseaseVariantDetailsPage(window, geneticAnalysisObject, diseaseName, variantIdentifier, currentPage)
})
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)
for variantIdentifierHex, _ := range diseaseVariantsMap{
variantIdentifier, err := encoding.DecodeHexStringTo3ByteArray(variantIdentifierHex)
if (err != nil) { return nil, err }
numberOfMutationsIsKnown, genomeNumberOfMutations, err := readGeneticAnalysis.GetPersonMonogenicDiseaseVariantInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, variantIdentifier, genomeIdentifier)
if (err != nil) { return nil, err }
if (numberOfMutationsIsKnown == false){
variantsList_Unknown = append(variantsList_Unknown, variantIdentifierHex)
continue
}
if (genomeNumberOfMutations == 0){
variantsList_0Mutations = append(variantsList_0Mutations, variantIdentifierHex)
} else if (genomeNumberOfMutations == 1) {
variantsList_1Mutation = append(variantsList_1Mutation, variantIdentifierHex)
} else if (genomeNumberOfMutations == 2){
variantsList_2Mutations = append(variantsList_2Mutations, variantIdentifierHex)
} 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
}
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1Row, widget.NewSeparator(), genomeNameRow, widget.NewSeparator(), variantsTestedRow, widget.NewSeparator(), phasedLociRow, widget.NewSeparator(), variantsGrid)
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
func setViewPersonGeneticAnalysisMonogenicDiseaseVariantDetailsPage(window fyne.Window, geneticAnalysisObject geneticAnalysis.PersonAnalysis, diseaseName string, variantIdentifier [3]byte, previousPage func()){
currentPage := func(){setViewPersonGeneticAnalysisMonogenicDiseaseVariantDetailsPage(window, geneticAnalysisObject, diseaseName, variantIdentifier, previousPage)}
title := getPageTitleCentered("Monogenic Disease Variant Details - " + diseaseName)
backButton := getBackButtonCentered(previousPage)
variantIdentifierHex := encoding.EncodeBytesToHexString(variantIdentifier[:])
variantObject, err := monogenicDiseases.GetMonogenicDiseaseVariantObject(diseaseName, variantIdentifierHex)
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(){
setViewMonogenicDiseaseVariantDetailsPage(window, diseaseName, variantIdentifierHex, currentPage)
})
variantNameRow := container.NewHBox(layout.NewSpacer(), variantNameLabel, variantNameText, variantNameHelpButton, layout.NewSpacer())
getGenomesHaveVariantGrid := func()(*fyne.Container, error){
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, onlyIncludeSharedGenomeIdentifier, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(geneticAnalysisObject)
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())
addGenomeRow := func(genomeName string, genomeIdentifier [16]byte, isACombinedGenome bool)error{
genomeMutationsKnown, genomeNumberOfMutations, err := readGeneticAnalysis.GetPersonMonogenicDiseaseVariantInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, variantIdentifier, genomeIdentifier)
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){
return "", errors.New("MyGenomeInfo for genome from analysisObject not found.")
}
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)
}
func setViewPersonGeneticAnalysisPolygenicDiseasesPage(window fyne.Window, personIdentifier string, analysisObject geneticAnalysis.PersonAnalysis, previousPage func()){
currentPage := func(){setViewPersonGeneticAnalysisPolygenicDiseasesPage(window, personIdentifier, analysisObject, previousPage)}
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){
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 }
diseaseNameLabel := getItalicLabelCentered("Disease Name")
riskScoreLabel := getItalicLabelCentered("Risk Score")
conflictExistsLabel := getItalicLabelCentered("Conflict Exists?")
emptyLabel := widget.NewLabel("")
diseaseNameColumn := container.NewVBox(diseaseNameLabel, widget.NewSeparator())
riskScoreColumn := container.NewVBox(riskScoreLabel, widget.NewSeparator())
conflictExistsColumn := container.NewVBox(conflictExistsLabel, widget.NewSeparator())
viewButtonsColumn := container.NewVBox(emptyLabel, widget.NewSeparator())
polygenicDiseaseNamesList, err := polygenicDiseases.GetPolygenicDiseaseNamesList()
if (err != nil) { return nil, err }
for _, diseaseName := range polygenicDiseaseNamesList{
diseaseNameText := getBoldLabelCentered(diseaseName)
personRiskScoreKnown, _, personRiskScoreFormatted, _, conflictExists, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(analysisObject, diseaseName, mainGenomeIdentifier)
if (err != nil) { return nil, err }
getPersonRiskScoreLabelText := func()string{
if (personRiskScoreKnown == false){
result := translate("Unknown")
return result
}
return personRiskScoreFormatted
}
personRiskScoreLabelText := getPersonRiskScoreLabelText()
riskScoreText := getBoldLabelCentered(personRiskScoreLabelText)
conflictExistsString := helpers.ConvertBoolToYesOrNoString(conflictExists)
conflictExistsLabel := getBoldLabelCentered(conflictExistsString)
viewDetailsButton := getWidgetCentered(widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
setViewPersonGeneticAnalysisPolygenicDiseaseDetailsPage(window, personIdentifier, analysisObject, diseaseName, currentPage)
}))
diseaseNameColumn.Add(diseaseNameText)
riskScoreColumn.Add(riskScoreText)
conflictExistsColumn.Add(conflictExistsLabel)
viewButtonsColumn.Add(viewDetailsButton)
diseaseNameColumn.Add(widget.NewSeparator())
riskScoreColumn.Add(widget.NewSeparator())
conflictExistsColumn.Add(widget.NewSeparator())
viewButtonsColumn.Add(widget.NewSeparator())
}
riskScoreHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setPolygenicDiseaseRiskScoreExplainerPage(window, currentPage)
})
riskScoreColumn.Add(riskScoreHelpButton)
diseasesContainer := container.NewHBox(layout.NewSpacer(), diseaseNameColumn, riskScoreColumn)
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)
}
func setViewPersonGeneticAnalysisPolygenicDiseaseDetailsPage(window fyne.Window, personIdentifier string, analysisObject geneticAnalysis.PersonAnalysis, diseaseName string, previousPage func()){
currentPage := func(){setViewPersonGeneticAnalysisPolygenicDiseaseDetailsPage(window, personIdentifier, analysisObject, diseaseName, previousPage)}
title := getPageTitleCentered("Viewing Genetic Analysis - " + diseaseName)
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 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)
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){
diseaseLociMap, err := polygenicDiseases.GetPolygenicDiseaseLociMap(diseaseName)
if (err != nil){ return nil, err }
totalNumberOfLoci := len(diseaseLociMap)
totalNumberOfLociString := helpers.ConvertIntToString(totalNumberOfLoci)
emptyLabelA := widget.NewLabel("")
genomeNameLabel := getItalicLabelCentered("Genome Name")
emptyLabelB := widget.NewLabel("")
riskScoreLabel := getItalicLabelCentered("Risk Score")
numberOfLabel := getItalicLabelCentered("Number of")
lociTestedLabel := getItalicLabelCentered("Loci Tested")
emptyLabelD := widget.NewLabel("")
emptyLabelE := widget.NewLabel("")
emptyLabelF := widget.NewLabel("")
emptyLabelG := widget.NewLabel("")
genomeNameColumn := container.NewVBox(emptyLabelA, genomeNameLabel, widget.NewSeparator())
riskScoreColumn := container.NewVBox(emptyLabelB, riskScoreLabel, widget.NewSeparator())
numberOfLociTestedColumn := container.NewVBox(numberOfLabel, lociTestedLabel, widget.NewSeparator())
viewLifetimeRiskButtonsColumn := container.NewVBox(emptyLabelD, emptyLabelE, widget.NewSeparator())
viewLociButtonsColumn := container.NewVBox(emptyLabelF, emptyLabelG, 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()
diseaseRiskScoreKnown, _, diseaseRiskScoreFormatted, numberOfLociTested, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(analysisObject, diseaseName, genomeIdentifier)
if (err != nil) { return err }
getRiskScoreLabelText := func()string{
if (diseaseRiskScoreKnown == false){
result := translate("Unknown")
return result
}
return diseaseRiskScoreFormatted
}
genomeRiskScoreLabelText := getRiskScoreLabelText()
riskScoreLabel := getBoldLabelCentered(genomeRiskScoreLabelText)
genomeNumberOfLociTestedString := helpers.ConvertIntToString(numberOfLociTested)
numberOfLociTestedLabel := getBoldLabelCentered(genomeNumberOfLociTestedString + "/" + totalNumberOfLociString)
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)
})
viewLociButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
setViewPersonGenomePolygenicDiseaseLociPage(window, analysisObject, diseaseName, genomeIdentifier, genomeName, currentPage)
})
genomeNameColumn.Add(genomeNameCell)
riskScoreColumn.Add(riskScoreLabel)
numberOfLociTestedColumn.Add(numberOfLociTestedLabel)
viewLifetimeRiskButtonsColumn.Add(viewLifetimeRiskButton)
viewLociButtonsColumn.Add(viewLociButton)
genomeNameColumn.Add(widget.NewSeparator())
riskScoreColumn.Add(widget.NewSeparator())
numberOfLociTestedColumn.Add(widget.NewSeparator())
viewLifetimeRiskButtonsColumn.Add(widget.NewSeparator())
viewLociButtonsColumn.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 }
}
riskScoreHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setPolygenicDiseaseRiskScoreExplainerPage(window, currentPage)
})
riskScoreColumn.Add(riskScoreHelpButton)
numberOfLociTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setPolygenicDiseaseNumberOfLociTestedExplainerPage(window, currentPage)
})
numberOfLociTestedColumn.Add(numberOfLociTestedHelpButton)
genomesContainer := container.NewHBox(layout.NewSpacer(), genomeNameColumn, riskScoreColumn, numberOfLociTestedColumn, viewLifetimeRiskButtonsColumn, viewLociButtonsColumn, 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(), diseaseNameRow, widget.NewSeparator(), genomesContainer)
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)
averageRiskString := helpers.ConvertFloat64ToStringRounded(averageRisk, 2)
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
}
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)
}
// This function provides a page to view the polygenic disease loci for a particular genome from a genetic analysis
func setViewPersonGenomePolygenicDiseaseLociPage(window fyne.Window, geneticAnalysisObject geneticAnalysis.PersonAnalysis, diseaseName string, genomeIdentifier [16]byte, genomeName string, previousPage func()){
setLoadingScreen(window, "Loading Polygenic Disease Loci", "Loading disease loci...")
currentPage := func(){setViewPersonGenomePolygenicDiseaseLociPage(window, geneticAnalysisObject, diseaseName, genomeIdentifier, genomeName, previousPage)}
title := getPageTitleCentered("View Disease Loci - " + diseaseName)
backButton := getBackButtonCentered(previousPage)
description1 := widget.NewLabel("Below are the disease loci results for this genome.")
lociHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setPolygenicDiseaseLociExplainerPage(window, currentPage)
})
description1Row := container.NewHBox(layout.NewSpacer(), description1, lociHelpButton, 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()
diseaseLociMap, err := polygenicDiseases.GetPolygenicDiseaseLociMap(diseaseName)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
numberOfLociTested := 0
lociList_PositiveWeight := make([]string, 0)
lociList_ZeroWeight := make([]string, 0)
lociList_NegativeWeight := make([]string, 0)
lociList_UnknownWeight := make([]string, 0)
for locusIdentifierHex, _ := range diseaseLociMap{
locusIdentifier, err := encoding.DecodeHexStringTo3ByteArray(locusIdentifierHex)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
locusRiskWeightIsKnown, genomeLocusRiskWeight, _, _, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, locusIdentifier, genomeIdentifier)
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
if (locusRiskWeightIsKnown == false){
lociList_UnknownWeight = append(lociList_UnknownWeight, locusIdentifierHex)
continue
}
numberOfLociTested += 1
if (genomeLocusRiskWeight > 0){
lociList_PositiveWeight = append(lociList_PositiveWeight, locusIdentifierHex)
} else if (genomeLocusRiskWeight == 0) {
lociList_ZeroWeight = append(lociList_ZeroWeight, locusIdentifierHex)
} else {
// genomeLocusRiskWeight < 0
lociList_NegativeWeight = append(lociList_NegativeWeight, locusIdentifierHex)
}
}
numberOfLociTestedString := helpers.ConvertIntToString(numberOfLociTested)
totalNumberOfLoci := len(diseaseLociMap)
totalNumberOfLociString := helpers.ConvertIntToString(totalNumberOfLoci)
lociTestedLabel := widget.NewLabel("Loci Tested:")
lociTestedText := getBoldLabel(numberOfLociTestedString + "/" + totalNumberOfLociString)
lociTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setPolygenicDiseaseNumberOfLociTestedExplainerPage(window, currentPage)
})
lociTestedRow := container.NewHBox(layout.NewSpacer(), lociTestedLabel, lociTestedText, lociTestedHelpButton, layout.NewSpacer())
getDiseaseLociGrid := func()(*fyne.Container, error){
locusNameLabel := getItalicLabelCentered("Locus Name")
riskWeightLabel := getItalicLabelCentered("Risk Weight")
oddsRatioLabel := getItalicLabelCentered("Odds Ratio")
emptyLabel := widget.NewLabel("")
locusNameColumn := container.NewVBox(locusNameLabel, widget.NewSeparator())
riskWeightColumn := container.NewVBox(riskWeightLabel, widget.NewSeparator())
oddsRatioColumn := container.NewVBox(oddsRatioLabel, widget.NewSeparator())
viewButtonsColumn := container.NewVBox(emptyLabel, widget.NewSeparator())
addLocusRow := func(locusIdentifierHex string)error{
diseaseLocusObject, exists := diseaseLociMap[locusIdentifierHex]
if (exists == false) {
return errors.New("Cannot add locusRow: diseaseLociMap missing locus: " + locusIdentifierHex)
}
locusRSID := diseaseLocusObject.LocusRSID
locusRSIDString := helpers.ConvertInt64ToString(locusRSID)
locusName := "rs" + locusRSIDString
locusNameLabel := getBoldLabelCentered(locusName)
locusIdentifier, err := encoding.DecodeHexStringTo3ByteArray(locusIdentifierHex)
if (err != nil) { return err }
locusRiskWeightIsKnown, genomeLocusRiskWeight, locusOddsRatioIsKnown, _, locusOddsRatioFormatted, err := readGeneticAnalysis.GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, locusIdentifier, genomeIdentifier)
if (err != nil) { return err }
getGenomeLocusRiskWeightText := func()string{
if (locusRiskWeightIsKnown == false){
result := translate("Unknown")
return result
}
locusRiskWeightString := helpers.ConvertIntToString(genomeLocusRiskWeight)
return locusRiskWeightString
}
locusRiskWeightText := getGenomeLocusRiskWeightText()
locusRiskWeightLabel := getBoldLabelCentered(locusRiskWeightText)
getOddsRatioText := func()string{
if (locusOddsRatioIsKnown == false){
result := translate("Unknown")
return result
}
return locusOddsRatioFormatted
}
locusOddsRatioText := getOddsRatioText()
genomeLocusOddsRatioLabel := getBoldLabelCentered(locusOddsRatioText)
viewLocusButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
setViewPersonGeneticAnalysisPolygenicDiseaseLocusDetailsPage(window, geneticAnalysisObject, diseaseName, locusIdentifier, currentPage)
})
locusNameColumn.Add(locusNameLabel)
riskWeightColumn.Add(locusRiskWeightLabel)
oddsRatioColumn.Add(genomeLocusOddsRatioLabel)
viewButtonsColumn.Add(viewLocusButton)
locusNameColumn.Add(widget.NewSeparator())
riskWeightColumn.Add(widget.NewSeparator())
oddsRatioColumn.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(lociList_PositiveWeight)
helpers.SortStringListToUnicodeOrder(lociList_NegativeWeight)
helpers.SortStringListToUnicodeOrder(lociList_ZeroWeight)
helpers.SortStringListToUnicodeOrder(lociList_UnknownWeight)
for _, locusIdentifier := range lociList_PositiveWeight{
err = addLocusRow(locusIdentifier)
if (err != nil) { return nil, err }
}
for _, locusIdentifier := range lociList_NegativeWeight{
err = addLocusRow(locusIdentifier)
if (err != nil) { return nil, err }
}
for _, locusIdentifier := range lociList_ZeroWeight{
err = addLocusRow(locusIdentifier)
if (err != nil) { return nil, err }
}
for _, locusIdentifier := range lociList_UnknownWeight{
err = addLocusRow(locusIdentifier)
if (err != nil) { return nil, err }
}
riskWeightHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setPolygenicDiseaseLocusRiskWeightExplainerPage(window, currentPage)
})
riskWeightColumn.Add(riskWeightHelpButton)
oddsRatioHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
//TODO
showUnderConstructionDialog(window)
})
oddsRatioColumn.Add(oddsRatioHelpButton)
diseaseLociGrid := container.NewHBox(layout.NewSpacer(), locusNameColumn, riskWeightColumn, oddsRatioColumn, viewButtonsColumn, layout.NewSpacer())
return diseaseLociGrid, nil
}
diseaseLociGrid, err := getDiseaseLociGrid()
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1Row, widget.NewSeparator(), genomeNameRow, widget.NewSeparator(), lociTestedRow, widget.NewSeparator(), diseaseLociGrid)
setPageContent(page, window)
}
// This function provides a page to view the details of a specific locus from a person genetic analysis
// It will show the locus details for all of the person's genomes
func setViewPersonGeneticAnalysisPolygenicDiseaseLocusDetailsPage(window fyne.Window, geneticAnalysisObject geneticAnalysis.PersonAnalysis, diseaseName string, locusIdentifier [3]byte, previousPage func()){
currentPage := func(){setViewPersonGeneticAnalysisPolygenicDiseaseLocusDetailsPage(window, geneticAnalysisObject, diseaseName, locusIdentifier, previousPage)}
title := getPageTitleCentered("Disease Locus Details - " + diseaseName)
backButton := getBackButtonCentered(previousPage)
locusIdentifierHex := encoding.EncodeBytesToHexString(locusIdentifier[:])
locusObject, err := polygenicDiseases.GetPolygenicDiseaseLocusObject(diseaseName, locusIdentifierHex)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
locusRSID := locusObject.LocusRSID
locusRSIDString := helpers.ConvertInt64ToString(locusRSID)
locusName := "rs" + locusRSIDString
description := getLabelCentered("Below is the locus result for the person's genomes.")
locusNameLabel := widget.NewLabel("Locus Name:")
locusNameText := getBoldLabel(locusName)
locusInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){
setViewPolygenicDiseaseLocusDetailsPage(window, diseaseName, locusIdentifierHex, currentPage)
})
locusNameRow := container.NewHBox(layout.NewSpacer(), locusNameLabel, locusNameText, locusInfoButton, layout.NewSpacer())
getGenomesLocusInfoGrid := func()(*fyne.Container, error){
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, onlyIncludeSharedGenomeIdentifier, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(geneticAnalysisObject)
if (err != nil) { return nil, err }
genomeNameLabel := getItalicLabelCentered("Genome Name")
riskWeightLabel := getItalicLabelCentered("Risk Weight")
oddsRatioLabel := getItalicLabelCentered("Odds Ratio")
genomeNameColumn := container.NewVBox(genomeNameLabel, widget.NewSeparator())
riskWeightColumn := container.NewVBox(riskWeightLabel, widget.NewSeparator())
oddsRatioColumn := container.NewVBox(oddsRatioLabel, widget.NewSeparator())
addGenomeRow := func(genomeName string, genomeIdentifier [16]byte, isACombinedGenome bool)error{
genomeRiskWeightKnown, genomeRiskWeight, genomeOddsRatioIsKnown, _, genomeOddsRatioFormatted, err := readGeneticAnalysis.GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, locusIdentifier, genomeIdentifier)
if (err != nil) { return err }
getGenomeRiskWeightText := func()string{
if (genomeRiskWeightKnown == false){
result := translate("Unknown")
return result
}
genomeRiskWeightString := helpers.ConvertIntToString(genomeRiskWeight)
return genomeRiskWeightString
}
genomeRiskWeightText := getGenomeRiskWeightText()
getGenomeOddsRatioText := func()string{
if (genomeOddsRatioIsKnown == false){
result := translate("Unknown")
return result
}
return genomeOddsRatioFormatted
}
genomeOddsRatioText := getGenomeOddsRatioText()
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)
riskWeightLabel := getBoldLabelCentered(genomeRiskWeightText)
riskWeightColumn.Add(riskWeightLabel)
oddsRatioLabel := getBoldLabelCentered(genomeOddsRatioText)
oddsRatioColumn.Add(oddsRatioLabel)
genomeNameColumn.Add(widget.NewSeparator())
riskWeightColumn.Add(widget.NewSeparator())
oddsRatioColumn.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 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 }
}
riskWeightHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setPolygenicDiseaseLocusRiskWeightExplainerPage(window, currentPage)
})
riskWeightColumn.Add(riskWeightHelpButton)
oddsRatioHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
//TODO
showUnderConstructionDialog(window)
})
oddsRatioColumn.Add(oddsRatioHelpButton)
genomesContainer := container.NewHBox(layout.NewSpacer(), genomeNameColumn, riskWeightColumn, oddsRatioColumn, layout.NewSpacer())
return genomesContainer, nil
}
genomesLocusInfoGrid, err := getGenomesLocusInfoGrid()
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), locusNameRow, widget.NewSeparator(), genomesLocusInfoGrid)
setPageContent(page, window)
}
func setViewPersonGeneticAnalysisDiscreteTraitsPage(window fyne.Window, personIdentifier string, analysisObject geneticAnalysis.PersonAnalysis, previousPage func()){
currentPage := func(){setViewPersonGeneticAnalysisDiscreteTraitsPage(window, personIdentifier, analysisObject, previousPage)}
title := getPageTitleCentered("Viewing Genetic Analysis - Discrete Traits")
backButton := getBackButtonCentered(previousPage)
description := getLabelCentered("Below is an analysis of the discrete 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 }
emptyLabel1 := widget.NewLabel("")
traitNameLabel := getItalicLabelCentered("Trait Name")
emptyLabel2 := widget.NewLabel("")
predictedOutcomeLabel := getItalicLabelCentered("Predicted Outcome")
quantityOfLabel := getItalicLabelCentered("Quantity Of")
lociKnownLabel := getItalicLabelCentered("Loci Known")
emptyLabel3 := widget.NewLabel("")
conflictExistsLabel := getItalicLabelCentered("Conflict Exists?")
emptyLabel4 := widget.NewLabel("")
emptyLabel5 := widget.NewLabel("")
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())
traitObjectsList, err := traits.GetTraitObjectsList()
if (err != nil) { return nil, err }
for _, traitObject := range traitObjectsList{
traitIsDiscreteOrNumeric := traitObject.DiscreteOrNumeric
if (traitIsDiscreteOrNumeric != "Discrete"){
continue
}
traitName := traitObject.TraitName
traitLociList := traitObject.LociList
traitRulesList := traitObject.RulesList
if (len(traitLociList) == 0 && len(traitRulesList) == 0){
// This trait does not have any rules or loci to analyze
// We cannot analyze it yet
continue
}
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
}
getPredictionLabel := func()fyne.Widget{
if (neuralNetworkExists == true){
if (neuralNetworkAnalysisExists == false){
result := getItalicLabel("Unknown")
return result
}
result := getBoldLabel(neuralNetworkPredictedOutcome)
return result
}
// anyRulesExist must be true
if (rulesAnalysisExists == false || rulesPredictedOutcomeExists == false){
result := getItalicLabel("Unknown")
return result
}
result := getBoldLabel(rulesPredictedOutcome)
return result
}
predictionLabel := getPredictionLabel()
predictionLabelCentered := getWidgetCentered(predictionLabel)
getQuantityOfLociKnown := func()int{
if (neuralNetworkExists == true){
return quantityOfLociKnown_NeuralNetwork
}
return quantityOfLociKnown_Rules
}
quantityOfLociKnown := getQuantityOfLociKnown()
getTotalQuantityOfLoci := func()int{
if (neuralNetworkExists == true){
totalQuantityOfLoci := len(traitLociList)
return totalQuantityOfLoci
}
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)
traitNameColumn.Add(widget.NewSeparator())
predictedOutcomeColumn.Add(widget.NewSeparator())
quantityOfLociKnownColumn.Add(widget.NewSeparator())
conflictExistsColumn.Add(widget.NewSeparator())
viewButtonsColumn.Add(widget.NewSeparator())
}
predictedOutcomeHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
//TODO
showUnderConstructionDialog(window)
})
predictedOutcomeColumn.Add(predictedOutcomeHelpButton)
quantityOfLociKnownHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
//TODO
showUnderConstructionDialog(window)
})
quantityOfLociKnownColumn.Add(quantityOfLociKnownHelpButton)
traitsContainer := container.NewHBox(layout.NewSpacer(), traitNameColumn, predictedOutcomeColumn, quantityOfLociKnownColumn)
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)
}
func setViewPersonGeneticAnalysisDiscreteTraitDetailsPage(window fyne.Window, personIdentifier string, analysisObject geneticAnalysis.PersonAnalysis, traitName string, previousPage func()){
currentPage := func(){setViewPersonGeneticAnalysisDiscreteTraitDetailsPage(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())
neuralNetworkExists, _ := geneticPredictionModels.GetGeneticPredictionModelBytes(traitName)
getGenomesContainer := func()(*fyne.Container, error){
emptyLabel1 := widget.NewLabel("")
genomeNameLabel := getItalicLabelCentered("Genome Name")
emptyLabel2 := widget.NewLabel("")
predictedOutcomeLabel := getItalicLabelCentered("Predicted Outcome")
emptyLabel3 := widget.NewLabel("")
predictionConfidenceLabel := getItalicLabelCentered("Prediction Confidence")
quantityOfLabel := getItalicLabelCentered("Quantity Of")
rulesTestedLabel := getItalicLabelCentered("Rules Tested")
emptyLabel4 := widget.NewLabel("")
emptyLabel5 := widget.NewLabel("")
genomeNameColumn := container.NewVBox()
predictedOutcomeColumn := container.NewVBox()
neuralNetworkPredictionConfidenceColumn := container.NewVBox()
numberOfRulesTestedColumn := container.NewVBox(quantityOfLabel, rulesTestedLabel, widget.NewSeparator())
viewDetailsButtonsColumn := container.NewVBox()
if (neuralNetworkExists == false){
// We only need an extra header row if the numberOfRulesTested column is shown
genomeNameColumn.Add(emptyLabel1)
predictedOutcomeColumn.Add(emptyLabel2)
neuralNetworkPredictionConfidenceColumn.Add(emptyLabel3)
viewDetailsButtonsColumn.Add(emptyLabel4)
}
genomeNameColumn.Add(genomeNameLabel)
predictedOutcomeColumn.Add(predictedOutcomeLabel)
neuralNetworkPredictionConfidenceColumn.Add(predictionConfidenceLabel)
viewDetailsButtonsColumn.Add(emptyLabel5)
genomeNameColumn.Add(widget.NewSeparator())
predictedOutcomeColumn.Add(widget.NewSeparator())
neuralNetworkPredictionConfidenceColumn.Add(widget.NewSeparator())
viewDetailsButtonsColumn.Add(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()
neuralNetworkExists, neuralNetworkAnalysisExists, neuralNetworkPredictedOutcome, neuralNetworkPredictionConfidence, _, _, anyRulesExist, rulesAnalysisExists, _, rulesPredictedOutcomeExists, rulesPredictedOutcome, quantityOfRulesTested, _, _, err := readGeneticAnalysis.GetPersonDiscreteTraitInfoFromGeneticAnalysis(analysisObject, traitName, genomeIdentifier)
if (err != nil) { return err }
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.")
}
getPredictedOutcomeLabel := func()fyne.Widget{
if (neuralNetworkExists == true){
if (neuralNetworkAnalysisExists == false){
predictedOutcomeLabel := getItalicLabel("Unknown")
return predictedOutcomeLabel
}
predictedOutcomeLabel := getBoldLabel(neuralNetworkPredictedOutcome)
return predictedOutcomeLabel
}
// anyRulesExist must be true
if (rulesAnalysisExists == false || rulesPredictedOutcomeExists == false){
predictedOutcomeLabel := getItalicLabel("Unknown")
return predictedOutcomeLabel
}
predictedOutcomeLabel := getBoldLabel(rulesPredictedOutcome)
return predictedOutcomeLabel
}
predictedOutcomeLabel := getPredictedOutcomeLabel()
predictedOutcomeLabelCentered := getWidgetCentered(predictedOutcomeLabel)
getNeuralNetworkConfidenceLabel := func()fyne.Widget{
if (neuralNetworkExists == false){
emptyLabel := widget.NewLabel("")
return emptyLabel
}
if (neuralNetworkAnalysisExists == false){
predictedOutcomeConfidenceLabel := getItalicLabel("Unknown")
return predictedOutcomeConfidenceLabel
}
neuralNetworkPredictionConfidenceString := helpers.ConvertIntToString(neuralNetworkPredictionConfidence)
predictedOutcomeConfidenceLabel := getBoldLabel(neuralNetworkPredictionConfidenceString + "%")
return predictedOutcomeConfidenceLabel
}
predictedOutcomeConfidenceLabel := getNeuralNetworkConfidenceLabel()
predictedOutcomeConfidenceLabelCentered := getWidgetCentered(predictedOutcomeConfidenceLabel)
getQuantityOfRulesTestedLabel := func()(fyne.Widget, error){
if (anyRulesExist == false){
emptyLabel := widget.NewLabel("")
return emptyLabel, nil
}
traitRulesMap, err := traits.GetTraitRulesMap(traitName)
if (err != nil){ return nil, err }
totalNumberOfRules := len(traitRulesMap)
totalNumberOfRulesString := helpers.ConvertIntToString(totalNumberOfRules)
if (rulesAnalysisExists == false){
quantityOfRulesTestedLabel := getItalicLabel("0/" + totalNumberOfRulesString)
return quantityOfRulesTestedLabel, nil
}
quantityOfRulesTestedString := helpers.ConvertIntToString(quantityOfRulesTested)
quantityOfRulesTestedLabel := getBoldLabel(quantityOfRulesTestedString + "/" + totalNumberOfRulesString)
return quantityOfRulesTestedLabel, nil
}
quantityOfRulesTestedLabel, err := getQuantityOfRulesTestedLabel()
if (err != nil) { return err }
quantityOfRulesTestedLabelCentered := getWidgetCentered(quantityOfRulesTestedLabel)
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)
neuralNetworkPredictionConfidenceColumn.Add(predictedOutcomeConfidenceLabelCentered)
numberOfRulesTestedColumn.Add(quantityOfRulesTestedLabelCentered)
viewDetailsButtonsColumn.Add(viewDetailsButton)
genomeNameColumn.Add(widget.NewSeparator())
predictedOutcomeColumn.Add(widget.NewSeparator())
neuralNetworkPredictionConfidenceColumn.Add(widget.NewSeparator())
numberOfRulesTestedColumn.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 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 }
}
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
})
neuralNetworkPredictionConfidenceColumn.Add(neuralNetworkConfidenceHelpButton)
numberOfRulesTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setDiscreteTraitQuantityOfRulesTestedExplainerPage(window, currentPage)
})
numberOfRulesTestedColumn.Add(numberOfRulesTestedHelpButton)
genomesContainer := container.NewHBox(layout.NewSpacer(), genomeNameColumn, predictedOutcomeColumn)
if (neuralNetworkExists == true){
genomesContainer.Add(neuralNetworkPredictionConfidenceColumn)
} else {
genomesContainer.Add(numberOfRulesTestedColumn)
}
genomesContainer.Add(viewDetailsButtonsColumn)
genomesContainer.Add(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)
}
// 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()){
setLoadingScreen(window, "Loading Trait Rules", "Loading trait rules...")
currentPage := func(){setViewPersonGenomeDiscreteTraitRulesPage(window, geneticAnalysisObject, traitName, genomeIdentifier, genomeName, previousPage)}
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(){
setDiscreteTraitRulesExplainerPage(window, currentPage)
})
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)
for ruleIdentifierHex, _ := range traitRulesMap{
ruleIdentifier, err := encoding.DecodeHexStringTo3ByteArray(ruleIdentifierHex)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
ruleStatusIsKnown, genomePassesRule, err := readGeneticAnalysis.GetPersonDiscreteTraitRuleInfoFromGeneticAnalysis(geneticAnalysisObject, traitName, ruleIdentifier, genomeIdentifier)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
if (ruleStatusIsKnown == false){
rulesList_Unknown = append(rulesList_Unknown, ruleIdentifierHex)
continue
}
numberOfRulesTested += 1
if (genomePassesRule == true){
rulesList_RulePassed = append(rulesList_RulePassed, ruleIdentifierHex)
} else {
rulesList_RuleNotPassed = append(rulesList_RuleNotPassed, ruleIdentifierHex)
}
}
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(){
setDiscreteTraitQuantityOfRulesTestedExplainerPage(window, currentPage)
})
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())
addRuleRow := func(ruleIdentifierHex string)error{
ruleIdentifierLabel := getBoldLabelCentered(ruleIdentifierHex)
ruleIdentifier, err := encoding.DecodeHexStringTo3ByteArray(ruleIdentifierHex)
if (err != nil){ return err }
ruleStatusIsKnown, genomePassesRule, err := readGeneticAnalysis.GetPersonDiscreteTraitRuleInfoFromGeneticAnalysis(geneticAnalysisObject, traitName, ruleIdentifier, genomeIdentifier)
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(){
setViewPersonGeneticAnalysisDiscreteTraitRuleDetailsPage(window, geneticAnalysisObject, traitName, ruleIdentifier, currentPage)
})
ruleIdentifierColumn.Add(ruleIdentifierLabel)
genomePassesRuleColumn.Add(genomePassesRuleLabel)
viewButtonsColumn.Add(viewRuleButton)
traitRuleObject, exists := traitRulesMap[ruleIdentifierHex]
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(){
setDiscreteTraitRuleOutcomeEffectsExplainerPage(window, currentPage)
})
ruleEffectsColumn.Add(ruleEffectsHelpButton)
genomePassesRuleHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setGenomePassesDiscreteTraitRuleExplainerPage(window, currentPage)
})
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
func setViewPersonGeneticAnalysisDiscreteTraitRuleDetailsPage(window fyne.Window, geneticAnalysisObject geneticAnalysis.PersonAnalysis, traitName string, ruleIdentifier [3]byte, previousPage func()){
currentPage := func(){setViewPersonGeneticAnalysisDiscreteTraitRuleDetailsPage(window, geneticAnalysisObject, traitName, ruleIdentifier, previousPage)}
title := getPageTitleCentered("Trait Rule Details - " + traitName)
backButton := getBackButtonCentered(previousPage)
description := getLabelCentered("Below is the rule result for the person's genomes.")
ruleIdentifierHex := encoding.EncodeBytesToHexString(ruleIdentifier[:])
ruleIdentifierLabel := widget.NewLabel("Rule Identifier:")
ruleIdentifierText := getBoldLabel(ruleIdentifierHex)
ruleInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){
setViewDiscreteTraitRuleDetailsPage(window, traitName, ruleIdentifierHex, currentPage)
})
ruleIdentifierRow := container.NewHBox(layout.NewSpacer(), ruleIdentifierLabel, ruleIdentifierText, ruleInfoButton, layout.NewSpacer())
getGenomesRuleInfoGrid := func()(*fyne.Container, error){
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, onlyIncludeSharedGenomeIdentifier, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(geneticAnalysisObject)
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())
addGenomeRow := func(genomeName string, genomeIdentifier [16]byte, isACombinedGenome bool)error{
genomeRuleStatusKnown, genomePassesRule, err := readGeneticAnalysis.GetPersonDiscreteTraitRuleInfoFromGeneticAnalysis(geneticAnalysisObject, traitName, ruleIdentifier, genomeIdentifier)
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){
return "", errors.New("MyGenomeInfo for genome from analysisObject not found.")
}
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(){
setGenomePassesDiscreteTraitRuleExplainerPage(window, currentPage)
})
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)
}