package gui // viewAnalysisGui_Couple.go implements pages to view a couple genetic analysis 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 "fyne.io/fyne/v2/canvas" import "seekia/resources/geneticReferences/monogenicDiseases" import "seekia/resources/geneticReferences/polygenicDiseases" import "seekia/resources/geneticReferences/traits" import "seekia/internal/appMemory" import "seekia/internal/createCharts" 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 "seekia/internal/statisticsDatum" import "slices" import "image" import "errors" func setViewCoupleGeneticAnalysisPage(window fyne.Window, person1Identifier string, person2Identifier string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, numberOfPerson1GenomesAnalyzed int, numberOfPerson2GenomesAnalyzed int, previousPage func()){ appMemory.SetMemoryEntry("CurrentViewedPage", "ViewCoupleGeneticAnalysisPage") currentPage := func(){setViewCoupleGeneticAnalysisPage(window, person1Identifier, person2Identifier, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, numberOfPerson1GenomesAnalyzed, numberOfPerson2GenomesAnalyzed, 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.") person1Found, person1Name, _, _, err := myPeople.GetPersonInfo(person1Identifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } if (person1Found == false){ setErrorEncounteredPage(window, errors.New("Couple person A not found."), previousPage) return } person2Found, person2Name, _, _, err := myPeople.GetPersonInfo(person2Identifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } if (person2Found == false){ setErrorEncounteredPage(window, errors.New("Couple person B not found."), previousPage) return } coupleNameLabel := widget.NewLabel("Couple Name:") coupleNameText := getBoldLabel(person1Name + " + " + person2Name) coupleNameRow := container.NewHBox(layout.NewSpacer(), coupleNameLabel, coupleNameText, layout.NewSpacer()) numberOfAnalyzedGenomesLabel := getLabelCentered("Number of Analyzed Genomes:") person1NameLabel := widget.NewLabel(person1Name + ":") person1NumberOfGenomesAnalyzedString := helpers.ConvertIntToString(numberOfPerson1GenomesAnalyzed) person1NumberOfGenomesAnalyzedLabel := getBoldLabel(person1NumberOfGenomesAnalyzedString) person1NumberOfAnalyzedGenomesRow := container.NewHBox(layout.NewSpacer(), person1NameLabel, person1NumberOfGenomesAnalyzedLabel, layout.NewSpacer()) person2NameLabel := widget.NewLabel(person2Name + ":") person2NumberOfGenomesAnalyzedString := helpers.ConvertIntToString(numberOfPerson2GenomesAnalyzed) person2NumberOfGenomesAnalyzedLabel := getBoldLabel(person2NumberOfGenomesAnalyzedString) person2NumberOfAnalyzedGenomesRow := container.NewHBox(layout.NewSpacer(), person2NameLabel, person2NumberOfGenomesAnalyzedLabel, layout.NewSpacer()) generalButton := widget.NewButton("General", func(){ //TODO: Offspring inbred rating (kinship of parents), ancestry showUnderConstructionDialog(window) }) monogenicDiseasesButton := widget.NewButton("Monogenic Diseases", func(){ setViewCoupleGeneticAnalysisMonogenicDiseasesPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, currentPage) }) polygenicDiseasesButton := widget.NewButton("Polygenic Diseases", func(){ setViewCoupleGeneticAnalysisPolygenicDiseasesPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, currentPage) }) traitsButton := widget.NewButton("Traits", func(){ setViewCoupleGeneticAnalysisTraitsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, currentPage) }) categoryButtonsGrid := getContainerCentered(container.NewGridWithColumns(1, generalButton, monogenicDiseasesButton, polygenicDiseasesButton, traitsButton)) page := container.NewVBox(title, backButton, widget.NewSeparator(), warningLabel1, warningLabel2, widget.NewSeparator(), coupleNameRow, widget.NewSeparator(), numberOfAnalyzedGenomesLabel, person1NumberOfAnalyzedGenomesRow, person2NumberOfAnalyzedGenomesRow, widget.NewSeparator(), categoryButtonsGrid) setPageContent(page, window) } func setViewCoupleGeneticAnalysisMonogenicDiseasesPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisMonogenicDiseasesPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, previousPage)} title := getPageTitleCentered("Viewing Genetic Analysis - Monogenic Diseases") backButton := getBackButtonCentered(previousPage) description := getLabelCentered("Below is an analysis of the monogenic disease probabilities for the couple's offspring.") //TODO: Sort so highest risk diseases are at the top. Everything else should be in normal order getMonogenicDiseasesGrid := func()(*fyne.Container, error){ pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier, secondGenomePairExists, _, _, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisObject) if (err != nil){ return nil, err } emptyLabelA := widget.NewLabel("") diseaseNameLabel := getItalicLabelCentered("Disease Name") offspringProbabilityOfLabel := getItalicLabelCentered("Offspring Probability Of") havingDiseaseLabel := getItalicLabelCentered("Having Disease") emptyLabelB := widget.NewLabel("") conflictExistsLabel := getItalicLabelCentered("Conflict Exists?") emptyLabelC := widget.NewLabel("") emptyLabelD := widget.NewLabel("") diseaseNameColumn := container.NewVBox(emptyLabelA, diseaseNameLabel, widget.NewSeparator()) offspringProbabilityOfHavingDiseaseColumn := container.NewVBox(offspringProbabilityOfLabel, havingDiseaseLabel, 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{ pair1GenomeIdentifierSlice := slices.Concat(pair1Person1GenomeIdentifier[:], pair1Person2GenomeIdentifier[:]) pair1GenomeIdentifier := [32]byte(pair1GenomeIdentifierSlice) offspringHasDiseaseProbabilityIsKnown, _, genomePairOffspringProbabilityOfHavingDisease, _, _, _, conflictExists, err := readGeneticAnalysis.GetOffspringMonogenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, pair1GenomeIdentifier) if (err != nil) { return nil, err } getOffspringProbabilityOfHavingDiseaseText := func()string{ if (offspringHasDiseaseProbabilityIsKnown == false){ result := translate("Unknown") return result } return genomePairOffspringProbabilityOfHavingDisease } offspringProbabilityOfHavingDiseaseText := getOffspringProbabilityOfHavingDiseaseText() diseaseNameText := getBoldLabelCentered(diseaseName) diseaseNameColumn.Add(diseaseNameText) offspringProbabilityOfHavingDiseaseLabel := getBoldLabelCentered(offspringProbabilityOfHavingDiseaseText) offspringProbabilityOfHavingDiseaseColumn.Add(offspringProbabilityOfHavingDiseaseLabel) conflictExistsString := helpers.ConvertBoolToYesOrNoString(conflictExists) conflictExistsLabel := getBoldLabelCentered(conflictExistsString) conflictExistsColumn.Add(conflictExistsLabel) viewDetailsButton := getWidgetCentered(widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewCoupleGeneticAnalysisMonogenicDiseaseDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, currentPage) })) viewButtonsColumn.Add(viewDetailsButton) diseaseNameColumn.Add(widget.NewSeparator()) offspringProbabilityOfHavingDiseaseColumn.Add(widget.NewSeparator()) conflictExistsColumn.Add(widget.NewSeparator()) viewButtonsColumn.Add(widget.NewSeparator()) } offspringProbabilityOfHavingDiseaseHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringProbabilityOfHavingMonogenicDiseaseExplainerPage(window, currentPage) }) offspringProbabilityOfHavingDiseaseColumn.Add(offspringProbabilityOfHavingDiseaseHelpButton) diseasesGrid := container.NewHBox(layout.NewSpacer(), diseaseNameColumn, offspringProbabilityOfHavingDiseaseColumn) if (secondGenomePairExists == true){ conflictExistsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setCoupleGeneticAnalysisConflictExistsExplainerPage(window, currentPage) }) conflictExistsColumn.Add(conflictExistsHelpButton) diseasesGrid.Add(conflictExistsColumn) } diseasesGrid.Add(viewButtonsColumn) diseasesGrid.Add(layout.NewSpacer()) return diseasesGrid, nil } monogenicDiseasesContainer, err := getMonogenicDiseasesGrid() if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), monogenicDiseasesContainer) setPageContent(page, window) } func setViewCoupleGeneticAnalysisMonogenicDiseaseDetailsPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisMonogenicDiseaseDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, previousPage)} title := getPageTitleCentered("Viewing Couple Analysis - " + diseaseName) backButton := getBackButtonCentered(previousPage) pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier, secondGenomePairExists, pair2Person1GenomeIdentifier, pair2Person2GenomeIdentifier, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisObject) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } getDescriptionSection := func()*fyne.Container{ if (secondGenomePairExists == false){ description := getLabelCentered("Below are the disease probabilities for the couple's offspring.") return description } description1 := getLabelCentered("Below are the disease probabilities for the couple's offspring.") description2 := getLabelCentered("Each genome pair combines different genomes from each person.") 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()) emptyLabel1 := widget.NewLabel("") emptyLabel2 := widget.NewLabel("") emptyLabel3 := widget.NewLabel("") emptyLabel4 := widget.NewLabel("") offspringProbabilityOfLabel1 := getItalicLabelCentered("Offspring Probability Of") havingDiseaseLabel := getItalicLabelCentered("Having Disease") offspringProbabilityOfLabel2 := getItalicLabelCentered("Offspring Probability Of") havingVariantLabel := getItalicLabelCentered("Having Variant") emptyLabel5 := widget.NewLabel("") emptyLabel6 := widget.NewLabel("") viewGenomePairButtonsColumn := container.NewVBox(emptyLabel1, emptyLabel2, widget.NewSeparator()) pairNameColumn := container.NewVBox(emptyLabel3, emptyLabel4, widget.NewSeparator()) offspringProbabilityOfHavingDiseaseColumn := container.NewVBox(offspringProbabilityOfLabel1, havingDiseaseLabel, widget.NewSeparator()) offspringProbabilityOfHavingVariantColumn := container.NewVBox(offspringProbabilityOfLabel2, havingVariantLabel, widget.NewSeparator()) viewOffspringVariantButtonsColumn := container.NewVBox(emptyLabel5, emptyLabel6, widget.NewSeparator()) addGenomePairRow := func(genomePairName string, person1GenomeIdentifier [16]byte, person2GenomeIdentifier [16]byte)error{ genomePairIdentifierSlice := slices.Concat(person1GenomeIdentifier[:], person2GenomeIdentifier[:]) genomePairIdentifier := [32]byte(genomePairIdentifierSlice) offspringProbabilityOfHavingDiseaseIsKnown, _, genomePairOffspringProbabilityOfHavingDisease, offspringProbabilityOfHavingAVariantIsKnown, _, genomePairOffspringProbabilityOfHavingAVariant, _, err := readGeneticAnalysis.GetOffspringMonogenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, genomePairIdentifier) if (err != nil) { return err } getOffspringProbabilityOfHavingDiseaseText := func()string{ if (offspringProbabilityOfHavingDiseaseIsKnown == false){ result := translate("Unknown") return result } return genomePairOffspringProbabilityOfHavingDisease } offspringProbabilityOfHavingDiseaseText := getOffspringProbabilityOfHavingDiseaseText() getOffspringProbabilityOfHavingAVariantText := func()string{ if (offspringProbabilityOfHavingAVariantIsKnown == false){ result := translate("Unknown") return result } return genomePairOffspringProbabilityOfHavingAVariant } offspringProbabilityOfHavingAVariantText := getOffspringProbabilityOfHavingAVariantText() genomePairNameLabel := getBoldLabelCentered(genomePairName) offspringProbabilityOfHavingDiseaseLabel := getBoldLabelCentered(offspringProbabilityOfHavingDiseaseText) offspringProbabilityOfHavingAVariantLabel := getBoldLabelCentered(offspringProbabilityOfHavingAVariantText) viewGenomePairButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewCoupleGeneticAnalysisMonogenicDiseaseGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, currentPage) }) viewOffspringVariantsButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewCoupleMonogenicDiseaseVariantsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, currentPage) }) viewGenomePairButtonsColumn.Add(viewGenomePairButton) pairNameColumn.Add(genomePairNameLabel) offspringProbabilityOfHavingDiseaseColumn.Add(offspringProbabilityOfHavingDiseaseLabel) offspringProbabilityOfHavingVariantColumn.Add(offspringProbabilityOfHavingAVariantLabel) viewOffspringVariantButtonsColumn.Add(viewOffspringVariantsButton) viewGenomePairButtonsColumn.Add(widget.NewSeparator()) pairNameColumn.Add(widget.NewSeparator()) offspringProbabilityOfHavingDiseaseColumn.Add(widget.NewSeparator()) offspringProbabilityOfHavingVariantColumn.Add(widget.NewSeparator()) viewOffspringVariantButtonsColumn.Add(widget.NewSeparator()) return nil } err = addGenomePairRow("Pair 1", pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } if (secondGenomePairExists == true){ err := addGenomePairRow("Pair 2", pair2Person1GenomeIdentifier, pair2Person2GenomeIdentifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } } offspringProbabilityOfHavingDiseaseHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringProbabilityOfHavingMonogenicDiseaseExplainerPage(window, currentPage) }) offspringProbabilityOfHavingVariantHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringProbabilityOfHavingVariantExplainerPage(window, currentPage) }) offspringProbabilityOfHavingDiseaseColumn.Add(offspringProbabilityOfHavingDiseaseHelpButton) offspringProbabilityOfHavingVariantColumn.Add(offspringProbabilityOfHavingVariantHelpButton) genomesContainer := container.NewHBox(layout.NewSpacer(), viewGenomePairButtonsColumn, pairNameColumn, offspringProbabilityOfHavingDiseaseColumn, offspringProbabilityOfHavingVariantColumn, viewOffspringVariantButtonsColumn, layout.NewSpacer()) page := container.NewVBox(title, backButton, widget.NewSeparator(), descriptionSection, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), genomesContainer) setPageContent(page, window) } func setViewCoupleGeneticAnalysisMonogenicDiseaseGenomePairDetailsPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, genomePairIdentifier [32]byte, genomePairName string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisMonogenicDiseaseGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, previousPage)} title := getPageTitleCentered("Viewing Couple Genome Pair Info") backButton := getBackButtonCentered(previousPage) description := getLabelCentered("Below is the disease information for both genomes in the genome pair.") 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()) genomePairLabel := widget.NewLabel("Genome Pair:") genomePairNameLabel := getBoldLabel(genomePairName) genomePairHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setCoupleGenomePairExplainerPage(window, currentPage) }) genomePairRow := container.NewHBox(layout.NewSpacer(), genomePairLabel, genomePairNameLabel, genomePairHelpButton, layout.NewSpacer()) diseaseVariantsMap, err := monogenicDiseases.GetMonogenicDiseaseVariantsMap(diseaseName) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } totalNumberOfVariants := len(diseaseVariantsMap) totalNumberOfVariantsString := helpers.ConvertIntToString(totalNumberOfVariants) emptyLabelA := widget.NewLabel("") personNameLabel := getItalicLabelCentered("Person Name") emptyLabelB := widget.NewLabel("") genomeNameLabel := getItalicLabelCentered("Genome Name") probabilityOfLabel := getItalicLabelCentered("Probability Of") passingAVariantLabel := getItalicLabelCentered("Passing A Variant") numberOfLabel := getItalicLabelCentered("Number Of") variantsTestedLabel := getItalicLabelCentered("Variants Tested") emptyLabelC := widget.NewLabel("") emptyLabelD := widget.NewLabel("") personNameColumn := container.NewVBox(emptyLabelA, personNameLabel, widget.NewSeparator()) genomeNameColumn := container.NewVBox(emptyLabelB, genomeNameLabel, widget.NewSeparator()) probabilityOfPassingAVariantColumn := container.NewVBox(probabilityOfLabel, passingAVariantLabel, widget.NewSeparator()) numberOfVariantsTestedColumn := container.NewVBox(numberOfLabel, variantsTestedLabel, widget.NewSeparator()) viewGenomeButtonsColumn := container.NewVBox(emptyLabelC, emptyLabelD, widget.NewSeparator()) addGenomeRow := func(isPerson1 bool, personName string, inputGenomeIdentifier [16]byte)error{ personAnalysisGenomeIdentifier, _, genomeIsCombined, combinedType, err := readGeneticAnalysis.GetMatchingPersonAnalysisGenomeIdentifierFromCoupleAnalysis(isPerson1, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, inputGenomeIdentifier) if (err != nil) { return err } personNameTrimmed, _, err := helpers.TrimAndFlattenString(personName, 10) if (err != nil) { return err } personNameLabel := getBoldLabelCentered(personNameTrimmed) getPersonAnalysisObject := func()geneticAnalysis.PersonAnalysis{ if (isPerson1 == true){ return person1AnalysisObject } return person2AnalysisObject } personAnalysisObject := getPersonAnalysisObject() getGenomeName := func()(string, error){ if (genomeIsCombined == false){ genomeFound, _, _, _, _, _, companyName, _, _, err := myGenomes.GetMyRawGenomeMetadata(personAnalysisGenomeIdentifier) if (err != nil) { return "", err } if (genomeFound == false){ return "", errors.New("MyGenomeInfo for genome from analysisObject not found.") } return companyName, nil } return combinedType, nil } genomeName, err := getGenomeName() if (err != nil) { return err } genomeNameLabel := getBoldLabelCentered(genomeName) probabilitiesKnown, _, _, probabilityOfPassingAVariantFormatted, personNumberOfVariantsTested, _, _, _, err := readGeneticAnalysis.GetPersonMonogenicDiseaseInfoFromGeneticAnalysis(personAnalysisObject, diseaseName, personAnalysisGenomeIdentifier) if (err != nil) { return err } getProbabilityOfPassingAVariantText := func()string{ if (probabilitiesKnown == false){ result := translate("Unknown") return result } return probabilityOfPassingAVariantFormatted } genomeProbabilityOfPassingAVariantText := getProbabilityOfPassingAVariantText() genomeProbabilityOfPassingAVariantLabel := getBoldLabelCentered(genomeProbabilityOfPassingAVariantText) personNumberOfVariantsTestedString := helpers.ConvertIntToString(personNumberOfVariantsTested) genomeNumberOfVariantsTestedLabel := getBoldLabelCentered(personNumberOfVariantsTestedString + "/" + totalNumberOfVariantsString) viewGenomeButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewPersonGenomeMonogenicDiseaseVariantsPage(window, personAnalysisObject, personAnalysisGenomeIdentifier, genomeName, diseaseName, currentPage) }) personNameColumn.Add(personNameLabel) genomeNameColumn.Add(genomeNameLabel) probabilityOfPassingAVariantColumn.Add(genomeProbabilityOfPassingAVariantLabel) numberOfVariantsTestedColumn.Add(genomeNumberOfVariantsTestedLabel) viewGenomeButtonsColumn.Add(viewGenomeButton) personNameColumn.Add(widget.NewSeparator()) genomeNameColumn.Add(widget.NewSeparator()) probabilityOfPassingAVariantColumn.Add(widget.NewSeparator()) numberOfVariantsTestedColumn.Add(widget.NewSeparator()) viewGenomeButtonsColumn.Add(widget.NewSeparator()) return nil } person1GenomeIdentifier, person2GenomeIdentifier := helpers.Split32ByteArrayInHalf(genomePairIdentifier) err = addGenomeRow(true, person1Name, person1GenomeIdentifier) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } err = addGenomeRow(false, person2Name, person2GenomeIdentifier) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } probabilityOfPassingAVariantHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setPersonProbabilityOfPassingVariantExplainerPage(window, currentPage) }) numberOfVariantsTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setNumberOfTestedVariantsExplainerPage(window, currentPage) }) probabilityOfPassingAVariantColumn.Add(probabilityOfPassingAVariantHelpButton) numberOfVariantsTestedColumn.Add(numberOfVariantsTestedHelpButton) genomesGrid := container.NewHBox(layout.NewSpacer(), personNameColumn, genomeNameColumn, probabilityOfPassingAVariantColumn, numberOfVariantsTestedColumn, viewGenomeButtonsColumn, layout.NewSpacer()) page := container.NewVBox(title, backButton, widget.NewSeparator(), description, diseaseNameRow, genomePairRow, widget.NewSeparator(), genomesGrid) setPageContent(page, window) } // This function provides a page to view the offspring disease variant probabilities for a particular genome pair from a couple genetic analysis func setViewCoupleMonogenicDiseaseVariantsPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, genomePairIdentifier [32]byte, genomePairName string, previousPage func()){ setLoadingScreen(window, "Loading Disease Variants", "Loading disease variants...") currentPage := func(){setViewCoupleMonogenicDiseaseVariantsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, previousPage)} title := getPageTitleCentered("View Offspring Disease Variants - " + diseaseName) backButton := getBackButtonCentered(previousPage) description1 := widget.NewLabel("Below are the disease variant probabilities for offspring from this genome pair.") variantsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setMonogenicDiseaseVariantsExplainerPage(window, currentPage) }) description1Row := container.NewHBox(layout.NewSpacer(), description1, variantsHelpButton, layout.NewSpacer()) genomePairLabel := widget.NewLabel("Genome Pair:") genomePairNameLabel := getBoldLabel(genomePairName) viewGenomePairInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewCoupleGeneticAnalysisMonogenicDiseaseGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, currentPage) }) genomePairRow := container.NewHBox(layout.NewSpacer(), genomePairLabel, genomePairNameLabel, viewGenomePairInfoButton, layout.NewSpacer()) //Outputs: // -int: Number of variants tested // -int: Number of loci tested // -int: Number of phased loci getVariantAndLociInfo := func()(int, int, int, error){ person1GenomeIdentifier, person2GenomeIdentifier := helpers.Split32ByteArrayInHalf(genomePairIdentifier) person1AnalysisGenomeIdentifier, _, _, _, err := readGeneticAnalysis.GetMatchingPersonAnalysisGenomeIdentifierFromCoupleAnalysis(true, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, person1GenomeIdentifier) if (err != nil) { return 0, 0, 0, err } _, _, _, _, person1NumberOfVariantsTested, person1NumberOfLociTested, person1NumberOfPhasedLoci, _, err := readGeneticAnalysis.GetPersonMonogenicDiseaseInfoFromGeneticAnalysis(person1AnalysisObject, diseaseName, person1AnalysisGenomeIdentifier) if (err != nil) { return 0, 0, 0, err } person2AnalysisGenomeIdentifier, _, _, _, err := readGeneticAnalysis.GetMatchingPersonAnalysisGenomeIdentifierFromCoupleAnalysis(false, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, person2GenomeIdentifier) if (err != nil) { return 0, 0, 0, err } _, _, _, _, person2NumberOfVariantsTested, person2NumberOfLociTested, person2NumberOfPhasedLoci, _, err := readGeneticAnalysis.GetPersonMonogenicDiseaseInfoFromGeneticAnalysis(person2AnalysisObject, diseaseName, person2AnalysisGenomeIdentifier) if (err != nil) { return 0, 0, 0, err } numberOfVariantsTested := person1NumberOfVariantsTested + person2NumberOfVariantsTested numberOfLociTested := person1NumberOfLociTested + person2NumberOfLociTested numberOfPhasedLoci := person1NumberOfPhasedLoci + person2NumberOfPhasedLoci return numberOfVariantsTested, numberOfLociTested, numberOfPhasedLoci, nil } numberOfVariantsTested, numberOfLociTested, numberOfPhasedLoci, err := getVariantAndLociInfo() if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } diseaseVariantsMap, err := monogenicDiseases.GetMonogenicDiseaseVariantsMap(diseaseName) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } totalNumberOfVariants := len(diseaseVariantsMap) * 2 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 with pages getVariantsGrid := func()(*fyne.Container, error){ emptyLabelA := widget.NewLabel("") variantNameLabel := getItalicLabelCentered("Variant Name") probabilityOfLabelA := getItalicLabelCentered("Probability Of") zeroMutationsLabel := getItalicLabelCentered("0 Mutations") probabilityOfLabelB := getItalicLabelCentered("Probability Of") oneMutationLabel := getItalicLabelCentered("1 Mutation") probabilityOfLabelC := getItalicLabelCentered("Probability Of") twoMutationsLabel := getItalicLabelCentered("2 Mutations") emptyLabelB := widget.NewLabel("") emptyLabelC := widget.NewLabel("") variantNameColumn := container.NewVBox(emptyLabelA, variantNameLabel, widget.NewSeparator()) probabilityOf0MutationsColumn := container.NewVBox(probabilityOfLabelA, zeroMutationsLabel, widget.NewSeparator()) probabilityOf1MutationColumn := container.NewVBox(probabilityOfLabelB, oneMutationLabel, widget.NewSeparator()) probabilityOf2MutationsColumn := container.NewVBox(probabilityOfLabelC, twoMutationsLabel, widget.NewSeparator()) variantInfoButtonsColumn := container.NewVBox(emptyLabelB, emptyLabelC, widget.NewSeparator()) addVariantRow := func(variantIdentifierHex string)error{ variantObject, exists := diseaseVariantsMap[variantIdentifierHex] if (exists == false){ return errors.New("Cannot add variant row: Variant missing from diseaseVariantsMap") } variantIdentifier, err := encoding.DecodeHexStringTo3ByteArray(variantIdentifierHex) if (err != nil){ return errors.New("addVariantRow called with invalid variantIdentifier: " + variantIdentifierHex) } variantName := variantObject.VariantNames[0] offspringProbabilitiesKnown, probabilityOf0MutationsLowerBound, probabilityOf0MutationsUpperBound, probabilityOf0MutationsFormatted, probabilityOf1MutationLowerBound, probabilityOf1MutationUpperBound, probabilityOf1MutationFormatted, probabilityOf2MutationsLowerBound, probabilityOf2MutationsUpperBound, probabilityOf2MutationsFormatted, err := readGeneticAnalysis.GetOffspringMonogenicDiseaseVariantInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, variantIdentifier, genomePairIdentifier) if (err != nil) { return err } getProbabilityOf0MutationsText := func()string{ if (offspringProbabilitiesKnown == false){ result := translate("Unknown") return result } if (probabilityOf0MutationsLowerBound == 0 && probabilityOf0MutationsUpperBound == 100){ result := translate("Unknown") return result } return probabilityOf0MutationsFormatted } probabilityOf0MutationsText := getProbabilityOf0MutationsText() getProbabilityOf1MutationText := func()string{ if (offspringProbabilitiesKnown == false){ result := translate("Unknown") return result } if (probabilityOf1MutationLowerBound == 0 && probabilityOf1MutationUpperBound == 100){ result := translate("Unknown") return result } return probabilityOf1MutationFormatted } probabilityOf1MutationText := getProbabilityOf1MutationText() getProbabilityOf2MutationsText := func()string{ if (offspringProbabilitiesKnown == false){ result := translate("Unknown") return result } if (probabilityOf2MutationsLowerBound == 0 && probabilityOf2MutationsUpperBound == 100){ result := translate("Unknown") return result } return probabilityOf2MutationsFormatted } probabilityOf2MutationsText := getProbabilityOf2MutationsText() variantNameLabel := getBoldLabelCentered(variantName) probabilityOf0MutationsLabel := getBoldLabelCentered(probabilityOf0MutationsText) probabilityOf1MutationLabel := getBoldLabelCentered(probabilityOf1MutationText) probabilityOf2MutationsLabel := getBoldLabelCentered(probabilityOf2MutationsText) viewVariantDetailsButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewCoupleGeneticAnalysisMonogenicDiseaseVariantDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, variantIdentifier, currentPage) }) variantNameColumn.Add(variantNameLabel) probabilityOf0MutationsColumn.Add(probabilityOf0MutationsLabel) probabilityOf1MutationColumn.Add(probabilityOf1MutationLabel) probabilityOf2MutationsColumn.Add(probabilityOf2MutationsLabel) variantInfoButtonsColumn.Add(viewVariantDetailsButton) variantNameColumn.Add(widget.NewSeparator()) probabilityOf0MutationsColumn.Add(widget.NewSeparator()) probabilityOf1MutationColumn.Add(widget.NewSeparator()) probabilityOf2MutationsColumn.Add(widget.NewSeparator()) variantInfoButtonsColumn.Add(widget.NewSeparator()) return nil } variantsWithNonZeroRiskList := make([]string, 0) variantsWithZeroRiskFullyKnownList := make([]string, 0) variantsWithZeroRiskPartiallyKnownList := make([]string, 0) variantsWithUnknownRiskList := make([]string, 0) for variantIdentifierHex, _ := range diseaseVariantsMap{ variantIdentifier, err := encoding.DecodeHexStringTo3ByteArray(variantIdentifierHex) if (err != nil){ return nil, errors.New("diseaseVariantsMap contains invalid variantIdentifier: " + variantIdentifierHex) } probabilitesKnown, probabilityOf0MutationsLowerBound, probabilityOf0MutationsUpperBound, _, probabilityOf1MutationLowerBound, probabilityOf1MutationUpperBound, _, probabilityOf2MutationsLowerBound, probabilityOf2MutationsUpperBound, _, err := readGeneticAnalysis.GetOffspringMonogenicDiseaseVariantInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, variantIdentifier, genomePairIdentifier) if (err != nil) { return nil, err } if (probabilitesKnown == false){ variantsWithUnknownRiskList = append(variantsWithUnknownRiskList, variantIdentifierHex) continue } if (probabilityOf1MutationLowerBound != 0 || probabilityOf2MutationsLowerBound != 0){ variantsWithNonZeroRiskList = append(variantsWithNonZeroRiskList, variantIdentifierHex) continue } // Risk is either 0 or partially unknown if (probabilityOf0MutationsLowerBound == 100 && probabilityOf0MutationsUpperBound == 100 && probabilityOf1MutationLowerBound == 0 && probabilityOf1MutationUpperBound == 0 && probabilityOf2MutationsLowerBound == 0 && probabilityOf2MutationsUpperBound == 0){ variantsWithZeroRiskFullyKnownList = append(variantsWithZeroRiskFullyKnownList, variantIdentifierHex) continue } variantsWithZeroRiskPartiallyKnownList = append(variantsWithZeroRiskPartiallyKnownList, variantIdentifierHex) } // We sort each list so the variants show up in the same order each time helpers.SortStringListToUnicodeOrder(variantsWithNonZeroRiskList) helpers.SortStringListToUnicodeOrder(variantsWithZeroRiskFullyKnownList) helpers.SortStringListToUnicodeOrder(variantsWithZeroRiskPartiallyKnownList) helpers.SortStringListToUnicodeOrder(variantsWithUnknownRiskList) for _, variantIdentifier := range variantsWithNonZeroRiskList{ err = addVariantRow(variantIdentifier) if (err != nil) { return nil, err } } for _, variantIdentifier := range variantsWithZeroRiskFullyKnownList{ err = addVariantRow(variantIdentifier) if (err != nil) { return nil, err } } for _, variantIdentifier := range variantsWithZeroRiskPartiallyKnownList{ err = addVariantRow(variantIdentifier) if (err != nil) { return nil, err } } for _, variantIdentifier := range variantsWithUnknownRiskList{ err = addVariantRow(variantIdentifier) if (err != nil) { return nil, err } } variantsGrid := container.NewHBox(layout.NewSpacer(), variantNameColumn, probabilityOf0MutationsColumn, probabilityOf1MutationColumn, probabilityOf2MutationsColumn, variantInfoButtonsColumn, 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(), genomePairRow, widget.NewSeparator(), variantsTestedRow, widget.NewSeparator(), phasedLociRow, widget.NewSeparator(), variantsGrid) setPageContent(page, window) } // This function provides a page to view the details of a specific variant from a genetic analysis // It will show the variant details for all of the couple's genome pairs func setViewCoupleGeneticAnalysisMonogenicDiseaseVariantDetailsPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, variantIdentifier [3]byte, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisMonogenicDiseaseVariantDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, variantIdentifier, previousPage)} title := getPageTitleCentered("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 disease variant analysis for the couple.") variantNameLabel := widget.NewLabel("Variant Name:") variantNameText := getBoldLabel(variantName) variantInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewMonogenicDiseaseVariantDetailsPage(window, diseaseName, variantIdentifierHex, currentPage) }) variantNameRow := container.NewHBox(layout.NewSpacer(), variantNameLabel, variantNameText, variantInfoButton, layout.NewSpacer()) getGenomePairsHaveVariantGrid := func()(*fyne.Container, error){ emptyLabelA := widget.NewLabel("") emptyLabelB := widget.NewLabel("") emptyLabelC := widget.NewLabel("") genomePairLabel := getItalicLabelCentered("Genome Pair") probabilityOfLabelA := getItalicLabelCentered("Probability Of") zeroMutationsLabel := getItalicLabelCentered("0 Mutations") probabilityOfLabelB := getItalicLabelCentered("Probability Of") oneMutationLabel := getItalicLabelCentered("1 Mutation") probabilityOfLabelC := getItalicLabelCentered("Probability Of") twoMutationsLabel := getItalicLabelCentered("2 Mutations") viewGenomePairInfoButtonsColumn := container.NewVBox(emptyLabelA, emptyLabelB, widget.NewSeparator()) genomePairNameColumn := container.NewVBox(emptyLabelC, genomePairLabel, widget.NewSeparator()) probabilityOf0MutationsColumn := container.NewVBox(probabilityOfLabelA, zeroMutationsLabel, widget.NewSeparator()) probabilityOf1MutationColumn := container.NewVBox(probabilityOfLabelB, oneMutationLabel, widget.NewSeparator()) probablityOf2MutationsColumn := container.NewVBox(probabilityOfLabelC, twoMutationsLabel, widget.NewSeparator()) addGenomePairRow := func(genomePairName string, genomePairIdentifier [32]byte)error{ probabilitiesKnown, probabilityOf0MutationsLowerBound, probabilityOf0MutationsUpperBound, probabilityOf0MutationsFormatted, probabilityOf1MutationLowerBound, probabilityOf1MutationUpperBound, probabilityOf1MutationFormatted, probabilityOf2MutationsLowerBound, probabilityOf2MutationsUpperBound, probabilityOf2MutationsFormatted, err := readGeneticAnalysis.GetOffspringMonogenicDiseaseVariantInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, variantIdentifier, genomePairIdentifier) if (err != nil) { return err } getProbabilityOf0MutationsText := func()string{ if (probabilitiesKnown == false){ result := translate("Unknown") return result } if (probabilityOf0MutationsLowerBound == 0 && probabilityOf0MutationsUpperBound == 100){ result := translate("Unknown") return result } return probabilityOf0MutationsFormatted } probabilityOf0MutationsText := getProbabilityOf0MutationsText() getProbabilityOf1MutationText := func()string{ if (probabilitiesKnown == false){ result := translate("Unknown") return result } if (probabilityOf1MutationLowerBound == 0 && probabilityOf1MutationUpperBound == 100){ result := translate("Unknown") return result } return probabilityOf1MutationFormatted } probabilityOf1MutationText := getProbabilityOf1MutationText() getProbabilityOf2MutationsText := func()string{ if (probabilitiesKnown == false){ result := translate("Unknown") return result } if (probabilityOf2MutationsLowerBound == 0 && probabilityOf2MutationsUpperBound == 100){ result := translate("Unknown") return result } return probabilityOf2MutationsFormatted } probabilityOf2MutationsText := getProbabilityOf2MutationsText() viewGenomePairInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewCoupleGeneticAnalysisMonogenicDiseaseGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, currentPage) }) genomePairNameLabel := getBoldLabelCentered(genomePairName) probabilityOf0MutationsLabel := getBoldLabelCentered(probabilityOf0MutationsText) probabilityOf1MutationLabel := getBoldLabelCentered(probabilityOf1MutationText) probabilityOf2MutationsLabel := getBoldLabelCentered(probabilityOf2MutationsText) viewGenomePairInfoButtonsColumn.Add(viewGenomePairInfoButton) genomePairNameColumn.Add(genomePairNameLabel) probabilityOf0MutationsColumn.Add(probabilityOf0MutationsLabel) probabilityOf1MutationColumn.Add(probabilityOf1MutationLabel) probablityOf2MutationsColumn.Add(probabilityOf2MutationsLabel) viewGenomePairInfoButtonsColumn.Add(widget.NewSeparator()) genomePairNameColumn.Add(widget.NewSeparator()) probabilityOf0MutationsColumn.Add(widget.NewSeparator()) probabilityOf1MutationColumn.Add(widget.NewSeparator()) probablityOf2MutationsColumn.Add(widget.NewSeparator()) return nil } pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier, secondGenomePairExists, pair2Person1GenomeIdentifier, pair2Person2GenomeIdentifier, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisObject) if (err != nil){ return nil, err } genomePair1Identifier := helpers.JoinTwo16ByteArrays(pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier) err = addGenomePairRow("Pair 1", genomePair1Identifier) if (err != nil) { return nil, err } if (secondGenomePairExists == true){ genomePair2Identifier := helpers.JoinTwo16ByteArrays(pair2Person1GenomeIdentifier, pair2Person2GenomeIdentifier) err := addGenomePairRow("Pair 2", genomePair2Identifier) if (err != nil) { return nil, err } } genomesContainer := container.NewHBox(layout.NewSpacer(), viewGenomePairInfoButtonsColumn, genomePairNameColumn, probabilityOf0MutationsColumn, probabilityOf1MutationColumn, probablityOf2MutationsColumn, layout.NewSpacer()) return genomesContainer, nil } genomePairsHaveVariantGrid, err := getGenomePairsHaveVariantGrid() if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), variantNameRow, widget.NewSeparator(), genomePairsHaveVariantGrid) setPageContent(page, window) } func setViewCoupleGeneticAnalysisPolygenicDiseasesPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisPolygenicDiseasesPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, previousPage)} title := getPageTitleCentered("Viewing Genetic Analysis - Polygenic Diseases") backButton := getBackButtonCentered(previousPage) description := getLabelCentered("Below is an analysis of the polygenic disease risk probabilities for the couple's offspring.") getDiseasesGrid := func()(*fyne.Container, error){ pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier, secondGenomePairExists, _, _, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisObject) if (err != nil){ return nil, err } diseaseNameLabel := getItalicLabelCentered("Disease Name") offspringRiskScoreLabel := getItalicLabelCentered("Offspring Risk Score") conflictExistsLabel := getItalicLabelCentered("Conflict Exists?") emptyLabel := widget.NewLabel("") diseaseNameColumn := container.NewVBox(diseaseNameLabel, widget.NewSeparator()) offspringRiskScoreColumn := container.NewVBox(offspringRiskScoreLabel, widget.NewSeparator()) conflictExistsColumn := container.NewVBox(conflictExistsLabel, widget.NewSeparator()) viewButtonsColumn := container.NewVBox(emptyLabel, widget.NewSeparator()) diseaseNamesList, err := polygenicDiseases.GetPolygenicDiseaseNamesList() if (err != nil) { return nil, err } for _, diseaseName := range diseaseNamesList{ mainGenomePairIdentifier := helpers.JoinTwo16ByteArrays(pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier) offspringRiskScoreKnown, _, offspringRiskScoreFormatted, _, _, conflictExists, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, mainGenomePairIdentifier) if (err != nil) { return nil, err } getRiskScoreLabelText := func()string{ if (offspringRiskScoreKnown == false){ result := translate("Unknown") return result } return offspringRiskScoreFormatted } offspringRiskScoreLabelText := getRiskScoreLabelText() diseaseNameText := getBoldLabelCentered(diseaseName) diseaseNameColumn.Add(diseaseNameText) offspringRiskScoreText := getBoldLabelCentered(offspringRiskScoreLabelText) offspringRiskScoreColumn.Add(offspringRiskScoreText) conflictExistsString := helpers.ConvertBoolToYesOrNoString(conflictExists) conflictExistsLabel := getBoldLabelCentered(conflictExistsString) conflictExistsColumn.Add(conflictExistsLabel) viewDetailsButton := getWidgetCentered(widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewCoupleGeneticAnalysisPolygenicDiseaseDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, currentPage) })) viewButtonsColumn.Add(viewDetailsButton) diseaseNameColumn.Add(widget.NewSeparator()) offspringRiskScoreColumn.Add(widget.NewSeparator()) conflictExistsColumn.Add(widget.NewSeparator()) viewButtonsColumn.Add(widget.NewSeparator()) } offspringRiskScoreHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringPolygenicDiseaseRiskScoreExplainerPage(window, currentPage) }) offspringRiskScoreColumn.Add(offspringRiskScoreHelpButton) diseasesGrid := container.NewHBox(layout.NewSpacer(), diseaseNameColumn, offspringRiskScoreColumn) if (secondGenomePairExists == true){ conflictExistsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setCoupleGeneticAnalysisConflictExistsExplainerPage(window, currentPage) }) conflictExistsColumn.Add(conflictExistsHelpButton) diseasesGrid.Add(conflictExistsColumn) } diseasesGrid.Add(viewButtonsColumn) diseasesGrid.Add(layout.NewSpacer()) return diseasesGrid, nil } diseasesGrid, err := getDiseasesGrid() if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), diseasesGrid) setPageContent(page, window) } func setViewCoupleGeneticAnalysisPolygenicDiseaseDetailsPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisPolygenicDiseaseDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, previousPage)} title := getPageTitleCentered("Viewing Couple Analysis - " + diseaseName) backButton := getBackButtonCentered(previousPage) pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier, secondGenomePairExists, pair2Person1GenomeIdentifier, pair2Person2GenomeIdentifier, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisObject) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } getDescriptionSection := func()*fyne.Container{ if (secondGenomePairExists == false){ description := getLabelCentered("Below is the disease analysis for the couple's offspring.") return description } description1 := getLabelCentered("Below is the disease analysis for the couple's offspring.") description2 := getLabelCentered("Each genome pair combines different genomes from each person.") descriptionsSection := container.NewVBox(description1, description2) return descriptionsSection } descriptionSection := getDescriptionSection() diseaseNameLabel := widget.NewLabel("Disease:") diseaseNameText := getBoldLabel(diseaseName) diseaseNameInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewPolygenicDiseaseDetailsPage(window, diseaseName, currentPage) }) diseaseNameRow := container.NewHBox(layout.NewSpacer(), diseaseNameLabel, diseaseNameText, diseaseNameInfoButton, layout.NewSpacer()) emptyLabel1 := widget.NewLabel("") emptyLabel2 := widget.NewLabel("") offspringRiskScoreLabel := getItalicLabelCentered("Offspring Risk Score") emptyLabel3 := widget.NewLabel("") emptyLabel4 := widget.NewLabel("") emptyLabel5 := widget.NewLabel("") viewGenomePairButtonsColumn := container.NewVBox(emptyLabel1, widget.NewSeparator()) pairNameColumn := container.NewVBox(emptyLabel2, widget.NewSeparator()) offspringRiskScoreColumn := container.NewVBox(offspringRiskScoreLabel, widget.NewSeparator()) viewSampleOffspringsChartButtonsColumn := container.NewVBox(emptyLabel3, widget.NewSeparator()) viewLifetimeRiskButtonsColumn := container.NewVBox(emptyLabel4, widget.NewSeparator()) viewOffspringLociButtonsColumn := container.NewVBox(emptyLabel5, widget.NewSeparator()) addGenomePairRow := func(genomePairName string, person1GenomeIdentifier [16]byte, person2GenomeIdentifier [16]byte)error{ genomePairIdentifier := helpers.JoinTwo16ByteArrays(person1GenomeIdentifier, person2GenomeIdentifier) offspringRiskScoreKnown, _, offspringRiskScoreFormatted, sampleOffspringRiskScoresList, numberOfLociTested, _, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, genomePairIdentifier) if (err != nil) { return err } getRiskScoreLabelText := func()string{ if (offspringRiskScoreKnown == false){ result := translate("Unknown") return result } return offspringRiskScoreFormatted } riskScoreLabelText := getRiskScoreLabelText() genomePairNameLabel := getBoldLabelCentered(genomePairName) offspringRiskScoreLabel := getBoldLabelCentered(riskScoreLabelText) viewGenomePairButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewCoupleGeneticAnalysisPolygenicDiseaseGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, currentPage) }) viewSampleOffspringsChartButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewPolygenicDiseaseSampleOffspringRiskScoresChart(window, diseaseName, sampleOffspringRiskScoresList, numberOfLociTested, currentPage) }) viewOffspringLifetimeRiskButton := widget.NewButtonWithIcon("", theme.HistoryIcon(), func(){ diseaseObject, err := polygenicDiseases.GetPolygenicDiseaseObject(diseaseName) if (err != nil){ setErrorEncounteredPage(window, err, currentPage) return } getPageMaleOrFemale := func()string{ //TODO: Get user sex from myLocalProfiles diseaseEffectedSex := diseaseObject.EffectedSex if (diseaseEffectedSex == "Both"){ return "Male" } return diseaseEffectedSex } pageMaleOrFemale := getPageMaleOrFemale() setViewPersonPolygenicDiseaseLifetimeProbabilitiesPage(window, diseaseName, genomePairName, pageMaleOrFemale, currentPage) }) viewOffspringLociButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewCouplePolygenicDiseaseLociPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, currentPage) }) viewGenomePairButtonsColumn.Add(viewGenomePairButton) pairNameColumn.Add(genomePairNameLabel) offspringRiskScoreColumn.Add(offspringRiskScoreLabel) viewSampleOffspringsChartButtonsColumn.Add(viewSampleOffspringsChartButton) viewLifetimeRiskButtonsColumn.Add(viewOffspringLifetimeRiskButton) viewOffspringLociButtonsColumn.Add(viewOffspringLociButton) viewGenomePairButtonsColumn.Add(widget.NewSeparator()) pairNameColumn.Add(widget.NewSeparator()) offspringRiskScoreColumn.Add(widget.NewSeparator()) viewSampleOffspringsChartButtonsColumn.Add(widget.NewSeparator()) viewLifetimeRiskButtonsColumn.Add(widget.NewSeparator()) viewOffspringLociButtonsColumn.Add(widget.NewSeparator()) return nil } err = addGenomePairRow("Pair 1", pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } if (secondGenomePairExists == true){ err := addGenomePairRow("Pair 2", pair2Person1GenomeIdentifier, pair2Person2GenomeIdentifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } } offspringRiskScoreHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringPolygenicDiseaseRiskScoreExplainerPage(window, currentPage) }) offspringRiskScoreColumn.Add(offspringRiskScoreHelpButton) genomesContainer := container.NewHBox(layout.NewSpacer(), viewGenomePairButtonsColumn, pairNameColumn, offspringRiskScoreColumn, viewSampleOffspringsChartButtonsColumn, viewLifetimeRiskButtonsColumn, viewOffspringLociButtonsColumn, layout.NewSpacer()) page := container.NewVBox(title, backButton, widget.NewSeparator(), descriptionSection, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), genomesContainer) setPageContent(page, window) } func setViewCoupleGeneticAnalysisPolygenicDiseaseGenomePairDetailsPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, genomePairIdentifier [32]byte, genomePairName string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisPolygenicDiseaseGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, previousPage)} title := getPageTitleCentered("Viewing Couple Genome Pair Info") backButton := getBackButtonCentered(previousPage) description := getLabelCentered("Below is the disease information for both genomes in the genome pair.") diseaseNameLabel := widget.NewLabel("Disease:") diseaseNameText := getBoldLabel(diseaseName) diseaseNameInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewPolygenicDiseaseDetailsPage(window, diseaseName, currentPage) }) diseaseNameRow := container.NewHBox(layout.NewSpacer(), diseaseNameLabel, diseaseNameText, diseaseNameInfoButton, layout.NewSpacer()) genomePairLabel := widget.NewLabel("Genome Pair:") genomePairNameLabel := getBoldLabel(genomePairName) genomePairHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setCoupleGenomePairExplainerPage(window, currentPage) }) genomePairRow := container.NewHBox(layout.NewSpacer(), genomePairLabel, genomePairNameLabel, genomePairHelpButton, layout.NewSpacer()) emptyLabelA := widget.NewLabel("") personNameLabel := getItalicLabelCentered("Person Name") emptyLabelB := widget.NewLabel("") genomeNameLabel := getItalicLabelCentered("Genome Name") emptyLabelC := widget.NewLabel("") riskScoreLabel := getItalicLabelCentered("Risk Score") numberOfLabel := getItalicLabelCentered("Number Of") lociTestedLabel := getItalicLabelCentered("Loci Tested") emptyLabelD := widget.NewLabel("") emptyLabelE := widget.NewLabel("") personNameColumn := container.NewVBox(emptyLabelA, personNameLabel, widget.NewSeparator()) genomeNameColumn := container.NewVBox(emptyLabelB, genomeNameLabel, widget.NewSeparator()) riskScoreColumn := container.NewVBox(emptyLabelC, riskScoreLabel, widget.NewSeparator()) numberOfLociTestedColumn := container.NewVBox(numberOfLabel, lociTestedLabel, widget.NewSeparator()) viewGenomeButtonsColumn := container.NewVBox(emptyLabelD, emptyLabelE, widget.NewSeparator()) addGenomeRow := func(isPerson1 bool, personName string, inputGenomeIdentifier [16]byte)error{ personAnalysisGenomeIdentifier, _, genomeIsCombined, combinedType, err := readGeneticAnalysis.GetMatchingPersonAnalysisGenomeIdentifierFromCoupleAnalysis(isPerson1, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, inputGenomeIdentifier) if (err != nil) { return err } personNameTrimmed, _, err := helpers.TrimAndFlattenString(personName, 10) if (err != nil) { return err } personNameLabel := getBoldLabelCentered(personNameTrimmed) getPersonAnalysisObject := func()geneticAnalysis.PersonAnalysis{ if (isPerson1 == true){ return person1AnalysisObject } return person2AnalysisObject } personAnalysisObject := getPersonAnalysisObject() getGenomeName := func()(string, error){ if (genomeIsCombined == false){ genomeFound, _, _, _, _, _, companyName, _, _, err := myGenomes.GetMyRawGenomeMetadata(personAnalysisGenomeIdentifier) if (err != nil) { return "", err } if (genomeFound == false){ return "", errors.New("MyGenomeInfo for genome from analysisObject not found.") } return companyName, nil } return combinedType, nil } genomeName, err := getGenomeName() if (err != nil) { return err } genomeNameLabel := getBoldLabelCentered(genomeName) personRiskScoreKnown, _, personRiskScoreFormatted, _, numberOfLociTested, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(personAnalysisObject, diseaseName, personAnalysisGenomeIdentifier) if (err != nil) { return err } getPersonRiskScoreLabelText := func()string{ if (personRiskScoreKnown == false){ result := translate("Unknown") return result } return personRiskScoreFormatted } personRiskScoreLabelText := getPersonRiskScoreLabelText() genomeRiskScoreLabel := getBoldLabelCentered(personRiskScoreLabelText) numberOfLociTestedString := helpers.ConvertIntToString(numberOfLociTested) numberOfLociTestedText := getBoldLabelCentered(numberOfLociTestedString) viewGenomeButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewPersonGenomePolygenicDiseaseLociPage(window, personAnalysisObject, diseaseName, personAnalysisGenomeIdentifier, genomeName, currentPage) }) personNameColumn.Add(personNameLabel) genomeNameColumn.Add(genomeNameLabel) riskScoreColumn.Add(genomeRiskScoreLabel) numberOfLociTestedColumn.Add(numberOfLociTestedText) viewGenomeButtonsColumn.Add(viewGenomeButton) personNameColumn.Add(widget.NewSeparator()) genomeNameColumn.Add(widget.NewSeparator()) riskScoreColumn.Add(widget.NewSeparator()) numberOfLociTestedColumn.Add(widget.NewSeparator()) viewGenomeButtonsColumn.Add(widget.NewSeparator()) return nil } person1GenomeIdentifier, person2GenomeIdentifier := helpers.Split32ByteArrayInHalf(genomePairIdentifier) err := addGenomeRow(true, person1Name, person1GenomeIdentifier) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } err = addGenomeRow(false, person2Name, person2GenomeIdentifier) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } riskScoreHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setPolygenicDiseaseRiskScoreExplainerPage(window, currentPage) }) riskScoreColumn.Add(riskScoreHelpButton) numberOfLociTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setPolygenicDiseaseNumberOfLociTestedExplainerPage(window, currentPage) }) numberOfLociTestedColumn.Add(numberOfLociTestedHelpButton) genomesGrid := container.NewHBox(layout.NewSpacer(), personNameColumn, genomeNameColumn, riskScoreColumn, numberOfLociTestedColumn, viewGenomeButtonsColumn, layout.NewSpacer()) page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), genomePairRow, widget.NewSeparator(), genomesGrid) setPageContent(page, window) } // This function provides a page to view the couple offspring locus probabilities for a particular genome pair func setViewCouplePolygenicDiseaseLociPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, genomePairIdentifier [32]byte, genomePairName string, previousPage func()){ setLoadingScreen(window, "Loading Polygenic Disease Loci", "Loading disease loci...") currentPage := func(){setViewCouplePolygenicDiseaseLociPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, previousPage)} title := getPageTitleCentered("View Offspring Disease Loci - " + diseaseName) backButton := getBackButtonCentered(previousPage) description1 := widget.NewLabel("Below are the disease loci probabilities for offspring from this genome pair.") diseaseLociHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setPolygenicDiseaseLociExplainerPage(window, currentPage) }) description1Row := container.NewHBox(layout.NewSpacer(), description1, diseaseLociHelpButton, layout.NewSpacer()) genomePairLabel := widget.NewLabel("Genome Pair:") genomePairNameLabel := getBoldLabel(genomePairName) viewGenomePairInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewCoupleGeneticAnalysisPolygenicDiseaseGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, currentPage) }) genomePairRow := container.NewHBox(layout.NewSpacer(), genomePairLabel, genomePairNameLabel, viewGenomePairInfoButton, layout.NewSpacer()) _, _, _, _, numberOfLociTested, _, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, genomePairIdentifier) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } numberOfLociTestedString := helpers.ConvertIntToString(numberOfLociTested) diseaseLociMap, err := polygenicDiseases.GetPolygenicDiseaseLociMap(diseaseName) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } totalNumberOfLoci := len(diseaseLociMap) totalNumberOfLociString := helpers.ConvertIntToString(totalNumberOfLoci) lociTestedLabel := widget.NewLabel("Loci Tested:") lociTestedText := getBoldLabel(numberOfLociTestedString + "/" + totalNumberOfLociString) lociTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringPolygenicDiseaseNumberOfLociTestedExplainerPage(window, currentPage) }) lociTestedRow := container.NewHBox(layout.NewSpacer(), lociTestedLabel, lociTestedText, lociTestedHelpButton, layout.NewSpacer()) getLociGrid := func()(*fyne.Container, error){ locusNameLabel := getItalicLabelCentered("Locus Name") offspringRiskWeightLabel := getItalicLabelCentered("Offspring Risk Weight") offspringOddsRatioLabel := getItalicLabelCentered("Offspring Odds Ratio") emptyLabel := widget.NewLabel("") locusNameColumn := container.NewVBox(locusNameLabel, widget.NewSeparator()) offspringRiskWeightColumn := container.NewVBox(offspringRiskWeightLabel, widget.NewSeparator()) offspringOddsRatioColumn := container.NewVBox(offspringOddsRatioLabel, widget.NewSeparator()) lociInfoButtonsColumn := container.NewVBox(emptyLabel, widget.NewSeparator()) addLocusRow := func(locusIdentifierHex string)error{ locusObject, exists := diseaseLociMap[locusIdentifierHex] if (exists == false) { return errors.New("Cannot add locus row: Locus not found in diseaseLociMap: " + locusIdentifierHex) } locusIdentifier, err := encoding.DecodeHexStringTo3ByteArray(locusIdentifierHex) if (err != nil) { return err } locusRSID := locusObject.LocusRSID locusRSIDString := helpers.ConvertInt64ToString(locusRSID) locusName := "rs" + locusRSIDString offspringRiskWeightKnown, offspringRiskWeight, offspringOddsRatioKnown, _, offspringOddsRatioFormatted, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseLocusInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, locusIdentifier, genomePairIdentifier) if (err != nil) { return err } getOffspringRiskWeightText := func()string{ if (offspringRiskWeightKnown == false){ unknownTextTranslated := translate("Unknown") return unknownTextTranslated } offspringRiskWeightString := helpers.ConvertIntToString(offspringRiskWeight) return offspringRiskWeightString } offspringRiskWeightText := getOffspringRiskWeightText() getOffspringOddsRatioText := func()string{ if (offspringOddsRatioKnown == false){ unknownTextTranslated := translate("Unknown") return unknownTextTranslated } return offspringOddsRatioFormatted } offspringOddsRatioText := getOffspringOddsRatioText() locusNameLabel := getBoldLabelCentered(locusName) locusRiskWeightLabel := getBoldLabelCentered(offspringRiskWeightText) locusOddsRatioLabel := getBoldLabelCentered(offspringOddsRatioText) viewLocusDetailsButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewCoupleGeneticAnalysisPolygenicDiseaseLocusDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, locusIdentifier, currentPage) }) locusNameColumn.Add(locusNameLabel) offspringRiskWeightColumn.Add(locusRiskWeightLabel) offspringOddsRatioColumn.Add(locusOddsRatioLabel) lociInfoButtonsColumn.Add(viewLocusDetailsButton) locusNameColumn.Add(widget.NewSeparator()) offspringRiskWeightColumn.Add(widget.NewSeparator()) offspringOddsRatioColumn.Add(widget.NewSeparator()) lociInfoButtonsColumn.Add(widget.NewSeparator()) return nil } lociWithKnownRiskWeightList := make([]string, 0) lociWithUnknownRiskWeightList := make([]string, 0) for locusIdentifierHex, _ := range diseaseLociMap{ locusIdentifier, err := encoding.DecodeHexStringTo3ByteArray(locusIdentifierHex) if (err != nil) { return nil, err } offspringRiskWeightKnown, _, _, _, _, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseLocusInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, locusIdentifier, genomePairIdentifier) if (err != nil) { return nil, err } if (offspringRiskWeightKnown == true){ lociWithKnownRiskWeightList = append(lociWithKnownRiskWeightList, locusIdentifierHex) } else { lociWithUnknownRiskWeightList = append(lociWithUnknownRiskWeightList, locusIdentifierHex) } } // We sort the lists so loci show up in the same order whenever page is refreshed helpers.SortStringListToUnicodeOrder(lociWithKnownRiskWeightList) helpers.SortStringListToUnicodeOrder(lociWithUnknownRiskWeightList) for _, locusIdentifier := range lociWithKnownRiskWeightList{ err = addLocusRow(locusIdentifier) if (err != nil) { return nil, err } } for _, locusIdentifier := range lociWithUnknownRiskWeightList{ err = addLocusRow(locusIdentifier) if (err != nil) { return nil, err } } offspringRiskWeightHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringPolygenicDiseaseLocusRiskWeightExplainerPage(window, currentPage) }) offspringRiskWeightColumn.Add(offspringRiskWeightHelpButton) offspringOddsRatioHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ //TODO showUnderConstructionDialog(window) }) offspringOddsRatioColumn.Add(offspringOddsRatioHelpButton) lociGrid := container.NewHBox(layout.NewSpacer(), locusNameColumn, offspringRiskWeightColumn, offspringOddsRatioColumn, lociInfoButtonsColumn, layout.NewSpacer()) return lociGrid, nil } lociGrid, err := getLociGrid() if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } page := container.NewVBox(title, backButton, widget.NewSeparator(), description1Row, widget.NewSeparator(), genomePairRow, widget.NewSeparator(), lociTestedRow, widget.NewSeparator(), lociGrid) setPageContent(page, window) } // This function provides a page to view the details of a specific locus from a genetic analysis // It will show the locus details for all of the couple's genome pairs func setViewCoupleGeneticAnalysisPolygenicDiseaseLocusDetailsPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, locusIdentifier [3]byte, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisPolygenicDiseaseLocusDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, 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 analysis for the couple.") 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()) getGenomePairsLocusInfoGrid := func()(*fyne.Container, error){ emptyLabel := widget.NewLabel("") genomePairLabel := getItalicLabelCentered("Genome Pair") offspringRiskWeightLabel := getItalicLabelCentered("Offspring Risk Weight") offspringOddsRatioLabel := getItalicLabelCentered("Offspring Odds Ratio") viewGenomePairInfoButtonsColumn := container.NewVBox(emptyLabel, widget.NewSeparator()) genomePairNameColumn := container.NewVBox(genomePairLabel, widget.NewSeparator()) offspringRiskWeightColumn := container.NewVBox(offspringRiskWeightLabel, widget.NewSeparator()) offspringOddsRatioColumn := container.NewVBox(offspringOddsRatioLabel, widget.NewSeparator()) addGenomePairRow := func(genomePairName string, genomePairIdentifier [32]byte)error{ offspringRiskWeightKnown, offspringRiskWeight, offspringOddsRatioKnown, _, offspringOddsRatioFormatted, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseLocusInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, locusIdentifier, genomePairIdentifier) if (err != nil) { return err } getOffspringRiskWeightText := func()string{ if (offspringRiskWeightKnown == false){ result := translate("Unknown") return result } offspringRiskWeightString := helpers.ConvertIntToString(offspringRiskWeight) return offspringRiskWeightString } offspringRiskWeightText := getOffspringRiskWeightText() getOffspringOddsRatioText := func()string{ if (offspringOddsRatioKnown == false){ result := translate("Unknown") return result } return offspringOddsRatioFormatted } offspringOddsRatioText := getOffspringOddsRatioText() viewGenomePairInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewCoupleGeneticAnalysisPolygenicDiseaseGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, currentPage) }) genomePairNameLabel := getBoldLabelCentered(genomePairName) offspringRiskWeightLabel := getBoldLabelCentered(offspringRiskWeightText) offspringOddsRatioLabel := getBoldLabelCentered(offspringOddsRatioText) viewGenomePairInfoButtonsColumn.Add(viewGenomePairInfoButton) genomePairNameColumn.Add(genomePairNameLabel) offspringRiskWeightColumn.Add(offspringRiskWeightLabel) offspringOddsRatioColumn.Add(offspringOddsRatioLabel) viewGenomePairInfoButtonsColumn.Add(widget.NewSeparator()) genomePairNameColumn.Add(widget.NewSeparator()) offspringRiskWeightColumn.Add(widget.NewSeparator()) offspringOddsRatioColumn.Add(widget.NewSeparator()) return nil } pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier, secondGenomePairExists, pair2Person1GenomeIdentifier, pair2Person2GenomeIdentifier, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisObject) if (err != nil){ return nil, err } genomePair1Identifier := helpers.JoinTwo16ByteArrays(pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier) err = addGenomePairRow("Pair 1", genomePair1Identifier) if (err != nil) { return nil, err } if (secondGenomePairExists == true){ genomePair2Identifier := helpers.JoinTwo16ByteArrays(pair2Person1GenomeIdentifier, pair2Person2GenomeIdentifier) err := addGenomePairRow("Pair 2", genomePair2Identifier) if (err != nil) { return nil, err } } offspringRiskWeightHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringPolygenicDiseaseLocusRiskWeightExplainerPage(window, currentPage) }) offspringOddsRatioHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ //TODO showUnderConstructionDialog(window) }) offspringRiskWeightColumn.Add(offspringRiskWeightHelpButton) offspringOddsRatioColumn.Add(offspringOddsRatioHelpButton) genomesContainer := container.NewHBox(layout.NewSpacer(), viewGenomePairInfoButtonsColumn, genomePairNameColumn, offspringRiskWeightColumn, offspringOddsRatioColumn, layout.NewSpacer()) return genomesContainer, nil } genomePairsLocusInfoGrid, err := getGenomePairsLocusInfoGrid() if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), locusNameRow, widget.NewSeparator(), genomePairsLocusInfoGrid) setPageContent(page, window) } // This is a page that shows the user 100 sample offspring polygenic disease risk scores on a bar chart // This helps users to visualize the standard deviation of their offspring's disease risk with this user func setViewPolygenicDiseaseSampleOffspringRiskScoresChart(window fyne.Window, diseaseName string, sampleOffspringRiskScoresList []int, numberOfLociTested int, previousPage func()){ currentPage := func(){setViewPolygenicDiseaseSampleOffspringRiskScoresChart(window, diseaseName, sampleOffspringRiskScoresList, numberOfLociTested, previousPage)} title := getPageTitleCentered("Viewing Sample Offspring Risk Scores Chart") backButton := getBackButtonCentered(previousPage) description := widget.NewLabel("Below is a chart of 100 sample offspring risk scores for this disease.") descriptionHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ //TODO showUnderConstructionDialog(window) }) descriptionRow := container.NewHBox(layout.NewSpacer(), description, descriptionHelpButton, layout.NewSpacer()) diseaseNameTitle := widget.NewLabel("Disease Name:") diseaseNameLabel := getBoldLabel(diseaseName) diseaseNameRow := container.NewHBox(layout.NewSpacer(), diseaseNameTitle, diseaseNameLabel, layout.NewSpacer()) if (len(sampleOffspringRiskScoresList) == 0){ description2 := getBoldLabelCentered("There is no offspring information available for this disease.") description3 := getBoldLabelCentered("This is because there were no disease loci for which both prospective parents had information.") page := container.NewVBox(title, backButton, widget.NewSeparator(), descriptionRow, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), description2, description3) setPageContent(page, window) return } diseaseLociMap, err := polygenicDiseases.GetPolygenicDiseaseLociMap(diseaseName) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } totalNumberOfLoci := len(diseaseLociMap) totalNumberOfLociString := helpers.ConvertIntToString(totalNumberOfLoci) numberOfLociTestedTitle := widget.NewLabel("Number Of Loci Tested:") numberOfLociTestedString := helpers.ConvertIntToString(numberOfLociTested) numberOfLociTestedLabel := getBoldLabel(numberOfLociTestedString + "/" + totalNumberOfLociString) lociTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringPolygenicDiseaseNumberOfLociTestedExplainerPage(window, currentPage) }) numberOfLociTestedRow := container.NewHBox(layout.NewSpacer(), numberOfLociTestedTitle, numberOfLociTestedLabel, lociTestedHelpButton, layout.NewSpacer()) getOffspringSampleRiskScoresChartImage := func()(image.Image, error){ // Map Structure: Risk Score -> Number of offspring with that risk score offspringRiskScoreCountsMap := make(map[int]int) for _, offspringRiskScore := range sampleOffspringRiskScoresList{ offspringRiskScoreCountsMap[offspringRiskScore] += 1 } //TODO: Move StatisticsDatum to its own package, because we are using it for non-user purposes, and will continue to do so offspringStatisticsDatumsList := make([]statisticsDatum.StatisticsDatum, 0) for riskScore:=0; riskScore <= 10; riskScore += 1{ getOffspringCount := func()int{ offspringCount, exists := offspringRiskScoreCountsMap[riskScore] if (exists == false){ return 0 } return offspringCount } offspringCount := getOffspringCount() riskScoreString := helpers.ConvertIntToString(riskScore) offspringCountString := helpers.ConvertIntToString(offspringCount) newStatisticsDatum := statisticsDatum.StatisticsDatum{ Label: riskScoreString + "/10", LabelFormatted: riskScoreString + "/10", Value: float64(offspringCount), ValueFormatted: offspringCountString, } offspringStatisticsDatumsList = append(offspringStatisticsDatumsList, newStatisticsDatum) } chartTitle := diseaseName + ": 100 Prospective Offspring Risk Scores" formatYAxisValuesFunction := func(inputRiskScore float64)(string, error){ inputRiskScoreInt, err := helpers.FloorFloat64ToInt(inputRiskScore) if (err != nil){ return "", err } inputRiskScoreString := helpers.ConvertIntToString(inputRiskScoreInt) return inputRiskScoreString, nil } offspringsChart, err := createCharts.CreateBarChart(chartTitle, offspringStatisticsDatumsList, formatYAxisValuesFunction, true, " Offspring") if (err != nil) { return nil, err } return offspringsChart, nil } offspringRiskScoresChartImage, err := getOffspringSampleRiskScoresChartImage() if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } viewChartFullscreenButton := getWidgetCentered(widget.NewButtonWithIcon("View Fullscreen", theme.ZoomInIcon(), func(){ setViewFullpageImagePage(window, offspringRiskScoresChartImage, currentPage) })) pageHeader := container.NewVBox(title, backButton, widget.NewSeparator(), descriptionRow, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), numberOfLociTestedRow, widget.NewSeparator()) chartFyneImage := canvas.NewImageFromImage(offspringRiskScoresChartImage) chartFyneImage.FillMode = canvas.ImageFillContain page := container.NewBorder(pageHeader, viewChartFullscreenButton, nil, nil, chartFyneImage) setPageContent(page, window) } func setViewCoupleGeneticAnalysisTraitsPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisTraitsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, previousPage)} title := getPageTitleCentered("Viewing Genetic Analysis - Traits") backButton := getBackButtonCentered(previousPage) description := getLabelCentered("Below is an analysis of the average trait scores for the couple's offspring.") getTraitsGrid := func()(*fyne.Container, error){ pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier, secondGenomePairExists, _, _, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisObject) if (err != nil){ return nil, err } traitNameLabel := getItalicLabelCentered("Trait Name") offspringOutcomeScoresLabel := getItalicLabelCentered("Offspring Outcome Scores") conflictExistsLabel := getItalicLabelCentered("Conflict Exists?") emptyLabel := widget.NewLabel("") traitNameColumn := container.NewVBox(traitNameLabel, widget.NewSeparator()) offspringOutcomeScoresColumn := container.NewVBox(offspringOutcomeScoresLabel, widget.NewSeparator()) conflictExistsColumn := container.NewVBox(conflictExistsLabel, widget.NewSeparator()) viewButtonsColumn := container.NewVBox(emptyLabel, widget.NewSeparator()) traitObjectsList, err := traits.GetTraitObjectsList() if (err != nil) { return nil, err } for _, traitObject := range traitObjectsList{ traitName := traitObject.TraitName traitRulesList := traitObject.RulesList if (len(traitRulesList) == 0){ // This trait does not have any rules // We cannot analyze it yet // We will add neural network prediction so we can predict these traits continue } mainGenomePairIdentifier := helpers.JoinTwo16ByteArrays(pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier) offspringOutcomeScoresKnown, offspringAverageOutcomeScoresMap, _, conflictExists, err := readGeneticAnalysis.GetOffspringTraitInfoFromGeneticAnalysis(coupleAnalysisObject, traitName, mainGenomePairIdentifier) if (err != nil) { return nil, err } // We add all of the columns except for the trait outcomes column, which may be multiple rows high traitNameText := getBoldLabelCentered(traitName) conflictExistsString := helpers.ConvertBoolToYesOrNoString(conflictExists) conflictExistsLabel := getBoldLabelCentered(conflictExistsString) viewDetailsButton := getWidgetCentered(widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewCoupleGeneticAnalysisTraitDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, traitName, currentPage) })) traitNameColumn.Add(traitNameText) conflictExistsColumn.Add(conflictExistsLabel) viewButtonsColumn.Add(viewDetailsButton) if (offspringOutcomeScoresKnown == false){ unknownTranslated := translate("Unknown") unknownLabel := getBoldLabelCentered(unknownTranslated) offspringOutcomeScoresColumn.Add(unknownLabel) } else { outcomeNamesList := helpers.GetListOfMapKeys(offspringAverageOutcomeScoresMap) // We have to sort outcome names so they always show up in the same order helpers.SortStringListToUnicodeOrder(outcomeNamesList) for index, outcomeName := range outcomeNamesList{ outcomeScore, exists := offspringAverageOutcomeScoresMap[outcomeName] if (exists == false){ return nil, errors.New("Outcome name not found in outcomeScoresMap after being found already.") } outcomeScoreString := helpers.ConvertFloat64ToStringRounded(outcomeScore, 2) outcomeRow := getBoldLabelCentered(outcomeName + ": " + outcomeScoreString) offspringOutcomeScoresColumn.Add(outcomeRow) if (index > 0){ emptyLabelA := widget.NewLabel("") emptyLabelB := widget.NewLabel("") emptyLabelC := widget.NewLabel("") traitNameColumn.Add(emptyLabelA) conflictExistsColumn.Add(emptyLabelB) viewButtonsColumn.Add(emptyLabelC) } } } traitNameColumn.Add(widget.NewSeparator()) offspringOutcomeScoresColumn.Add(widget.NewSeparator()) conflictExistsColumn.Add(widget.NewSeparator()) viewButtonsColumn.Add(widget.NewSeparator()) } offspringOutcomeScoresHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringTraitOutcomeScoresExplainerPage(window, currentPage) }) offspringOutcomeScoresColumn.Add(offspringOutcomeScoresHelpButton) traitsGrid := container.NewHBox(layout.NewSpacer(), traitNameColumn, offspringOutcomeScoresColumn) if (secondGenomePairExists == true){ conflictExistsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setCoupleGeneticAnalysisConflictExistsExplainerPage(window, currentPage) }) conflictExistsColumn.Add(conflictExistsHelpButton) traitsGrid.Add(conflictExistsColumn) } traitsGrid.Add(viewButtonsColumn) traitsGrid.Add(layout.NewSpacer()) return traitsGrid, nil } traitsGrid, err := getTraitsGrid() if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), traitsGrid) setPageContent(page, window) } func setViewCoupleGeneticAnalysisTraitDetailsPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, traitName string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisTraitDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, traitName, previousPage)} title := getPageTitleCentered("Viewing Couple Analysis - " + traitName) backButton := getBackButtonCentered(previousPage) pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier, secondGenomePairExists, pair2Person1GenomeIdentifier, pair2Person2GenomeIdentifier, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisObject) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } getDescriptionSection := func()*fyne.Container{ if (secondGenomePairExists == false){ description := getLabelCentered("Below is the trait analysis for the couple's offspring.") return description } description1 := getLabelCentered("Below is the trait analysis for the couple's offspring.") description2 := getLabelCentered("Each genome pair combines different genomes from each person.") descriptionsSection := container.NewVBox(description1, description2) return descriptionsSection } descriptionSection := getDescriptionSection() traitNameLabel := widget.NewLabel("Trait:") traitNameText := getBoldLabel(traitName) traitNameInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewTraitDetailsPage(window, traitName, currentPage) }) traitNameRow := container.NewHBox(layout.NewSpacer(), traitNameLabel, traitNameText, traitNameInfoButton, layout.NewSpacer()) emptyLabelA := widget.NewLabel("") emptyLabelB := widget.NewLabel("") offspringOutcomeScoresLabel := getItalicLabelCentered("Offspring Outcome Scores") emptyLabelC := widget.NewLabel("") viewGenomePairButtonsColumn := container.NewVBox(emptyLabelA, widget.NewSeparator()) pairNameColumn := container.NewVBox(emptyLabelB, widget.NewSeparator()) offspringOutcomeScoresColumn := container.NewVBox(offspringOutcomeScoresLabel, widget.NewSeparator()) viewOffspringRulesButtonsColumn := container.NewVBox(emptyLabelC, widget.NewSeparator()) addGenomePairRow := func(genomePairName string, person1GenomeIdentifier [16]byte, person2GenomeIdentifier [16]byte)error{ genomePairIdentifier := helpers.JoinTwo16ByteArrays(person1GenomeIdentifier, person2GenomeIdentifier) genomePairNameLabel := getBoldLabelCentered(genomePairName) viewGenomePairButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewCoupleGeneticAnalysisTraitGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, traitName, genomePairIdentifier, genomePairName, currentPage) }) viewOffspringRulesButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewCoupleTraitRulesPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, traitName, genomePairIdentifier, genomePairName, currentPage) }) // We add all of the columns except for the trait rule column, which may be multiple rows high viewGenomePairButtonsColumn.Add(viewGenomePairButton) pairNameColumn.Add(genomePairNameLabel) viewOffspringRulesButtonsColumn.Add(viewOffspringRulesButton) offspringOutcomeScoresKnown, offspringOutcomeScoresMap, _, _, err := readGeneticAnalysis.GetOffspringTraitInfoFromGeneticAnalysis(coupleAnalysisObject, traitName, genomePairIdentifier) if (err != nil) { return err } if (offspringOutcomeScoresKnown == false){ unknownTranslated := translate("Unknown") unknownLabel := getBoldLabelCentered(unknownTranslated) offspringOutcomeScoresColumn.Add(unknownLabel) } else { outcomeNamesList := helpers.GetListOfMapKeys(offspringOutcomeScoresMap) // We have to sort the outcome names so they always show up in the same order helpers.SortStringListToUnicodeOrder(outcomeNamesList) for index, outcomeName := range outcomeNamesList{ outcomeScore, exists := offspringOutcomeScoresMap[outcomeName] if (exists == false){ return errors.New("Outcome name not found in outcome scores map after being found already.") } outcomeScoreString := helpers.ConvertFloat64ToStringRounded(outcomeScore, 2) outcomeRow := getBoldLabelCentered(outcomeName + ": " + outcomeScoreString) offspringOutcomeScoresColumn.Add(outcomeRow) if (index > 0){ emptyLabelA := widget.NewLabel("") emptyLabelB := widget.NewLabel("") emptyLabelC := widget.NewLabel("") pairNameColumn.Add(emptyLabelA) viewGenomePairButtonsColumn.Add(emptyLabelB) viewOffspringRulesButtonsColumn.Add(emptyLabelC) } } } viewGenomePairButtonsColumn.Add(widget.NewSeparator()) pairNameColumn.Add(widget.NewSeparator()) offspringOutcomeScoresColumn.Add(widget.NewSeparator()) viewOffspringRulesButtonsColumn.Add(widget.NewSeparator()) return nil } err = addGenomePairRow("Pair 1", pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } if (secondGenomePairExists == true){ err := addGenomePairRow("Pair 2", pair2Person1GenomeIdentifier, pair2Person2GenomeIdentifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } } offspringOutcomeScoresHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringTraitOutcomeScoresExplainerPage(window, currentPage) }) offspringOutcomeScoresColumn.Add(offspringOutcomeScoresHelpButton) genomesContainer := container.NewHBox(layout.NewSpacer(), viewGenomePairButtonsColumn, pairNameColumn, offspringOutcomeScoresColumn, viewOffspringRulesButtonsColumn, layout.NewSpacer()) page := container.NewVBox(title, backButton, widget.NewSeparator(), descriptionSection, widget.NewSeparator(), traitNameRow, widget.NewSeparator(), genomesContainer) setPageContent(page, window) } func setViewCoupleGeneticAnalysisTraitGenomePairDetailsPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, traitName string, genomePairIdentifier [32]byte, genomePairName string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisTraitGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, traitName, genomePairIdentifier, genomePairName, previousPage)} title := getPageTitleCentered("Viewing Couple Genome Pair Info") backButton := getBackButtonCentered(previousPage) description := getLabelCentered("Below is the trait information for both genomes in the genome pair.") traitNameLabel := widget.NewLabel("Trait:") traitNameText := getBoldLabel(traitName) traitNameInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewTraitDetailsPage(window, traitName, currentPage) }) traitNameRow := container.NewHBox(layout.NewSpacer(), traitNameLabel, traitNameText, traitNameInfoButton, layout.NewSpacer()) genomePairLabel := widget.NewLabel("Genome Pair:") genomePairNameLabel := getBoldLabel(genomePairName) genomePairHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setCoupleGenomePairExplainerPage(window, currentPage) }) genomePairRow := container.NewHBox(layout.NewSpacer(), genomePairLabel, genomePairNameLabel, genomePairHelpButton, layout.NewSpacer()) emptyLabelA := widget.NewLabel("") personNameLabel := getItalicLabelCentered("Person Name") emptyLabelB := widget.NewLabel("") genomeNameLabel := getItalicLabelCentered("Genome Name") emptyLabelC := widget.NewLabel("") outcomeScoresLabel := getItalicLabelCentered("Outcome Scores") numberOfLabel := getItalicLabelCentered("Number Of") rulesTestedLabel := getItalicLabelCentered("Rules Tested") emptyLabelD := widget.NewLabel("") emptyLabelE := widget.NewLabel("") personNameColumn := container.NewVBox(emptyLabelA, personNameLabel, widget.NewSeparator()) genomeNameColumn := container.NewVBox(emptyLabelB, genomeNameLabel, widget.NewSeparator()) outcomeScoresColumn := container.NewVBox(emptyLabelC, outcomeScoresLabel, widget.NewSeparator()) numberOfRulesTestedColumn := container.NewVBox(numberOfLabel, rulesTestedLabel, widget.NewSeparator()) viewGenomeButtonsColumn := container.NewVBox(emptyLabelD, emptyLabelE, widget.NewSeparator()) addGenomeRow := func(isPerson1 bool, personName string, inputGenomeIdentifier [16]byte)error{ personAnalysisGenomeIdentifier, _, genomeIsCombined, combinedType, err := readGeneticAnalysis.GetMatchingPersonAnalysisGenomeIdentifierFromCoupleAnalysis(isPerson1, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, inputGenomeIdentifier) if (err != nil) { return err } personNameTrimmed, _, err := helpers.TrimAndFlattenString(personName, 10) if (err != nil) { return err } personNameLabel := getBoldLabelCentered(personNameTrimmed) getPersonAnalysisObject := func()geneticAnalysis.PersonAnalysis{ if (isPerson1 == true){ return person1AnalysisObject } return person2AnalysisObject } personAnalysisObject := getPersonAnalysisObject() getGenomeName := func()(string, error){ if (genomeIsCombined == false){ genomeFound, _, _, _, _, _, companyName, _, _, err := myGenomes.GetMyRawGenomeMetadata(personAnalysisGenomeIdentifier) if (err != nil) { return "", err } if (genomeFound == false){ return "", errors.New("MyGenomeInfo for genome from analysisObject not found.") } return companyName, nil } return combinedType, nil } genomeName, err := getGenomeName() if (err != nil) { return err } genomeNameLabel := getBoldLabelCentered(genomeName) // We add all of the columns except for the trait rule column, which may be multiple rows high _, anyTraitRuleTested, outcomeScoresMap, numberOfRulesTested, _, err := readGeneticAnalysis.GetPersonTraitInfoFromGeneticAnalysis(personAnalysisObject, traitName, personAnalysisGenomeIdentifier) if (err != nil) { return err } numberOfRulesTestedString := helpers.ConvertIntToString(numberOfRulesTested) numberOfRulesTestedText := getBoldLabelCentered(numberOfRulesTestedString) viewGenomeButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewPersonGenomeTraitRulesPage(window, personAnalysisObject, traitName, personAnalysisGenomeIdentifier, genomeName, currentPage) }) personNameColumn.Add(personNameLabel) genomeNameColumn.Add(genomeNameLabel) numberOfRulesTestedColumn.Add(numberOfRulesTestedText) viewGenomeButtonsColumn.Add(viewGenomeButton) if (anyTraitRuleTested == false){ unknownTranslated := translate("Unknown") unknownLabel := getBoldLabelCentered(unknownTranslated) outcomeScoresColumn.Add(unknownLabel) } else { outcomeNamesList := helpers.GetListOfMapKeys(outcomeScoresMap) // We have to sort the outcome names so they always show up in the same order helpers.SortStringListToUnicodeOrder(outcomeNamesList) for index, outcomeName := range outcomeNamesList{ outcomeScore, exists := outcomeScoresMap[outcomeName] if (exists == false){ return errors.New("Outcome name not found in outcome scores map after being found already.") } outcomeScoreString := helpers.ConvertIntToString(outcomeScore) outcomeRow := getBoldLabelCentered(outcomeName + ": " + outcomeScoreString) outcomeScoresColumn.Add(outcomeRow) if (index > 0){ emptyLabelA := widget.NewLabel("") emptyLabelB := widget.NewLabel("") emptyLabelC := widget.NewLabel("") emptyLabelD := widget.NewLabel("") personNameColumn.Add(emptyLabelA) genomeNameColumn.Add(emptyLabelB) numberOfRulesTestedColumn.Add(emptyLabelC) viewGenomeButtonsColumn.Add(emptyLabelD) } } } personNameColumn.Add(widget.NewSeparator()) genomeNameColumn.Add(widget.NewSeparator()) outcomeScoresColumn.Add(widget.NewSeparator()) numberOfRulesTestedColumn.Add(widget.NewSeparator()) viewGenomeButtonsColumn.Add(widget.NewSeparator()) return nil } person1GenomeIdentifier, person2GenomeIdentifier := helpers.Split32ByteArrayInHalf(genomePairIdentifier) err := addGenomeRow(true, person1Name, person1GenomeIdentifier) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } err = addGenomeRow(false, person2Name, person2GenomeIdentifier) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } outcomeScoresHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringTraitOutcomeScoresExplainerPage(window, currentPage) }) outcomeScoresColumn.Add(outcomeScoresHelpButton) numberOfRulesTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringTraitNumberOfRulesTestedExplainerPage(window, currentPage) }) numberOfRulesTestedColumn.Add(numberOfRulesTestedHelpButton) genomesGrid := container.NewHBox(layout.NewSpacer(), personNameColumn, genomeNameColumn, outcomeScoresColumn, numberOfRulesTestedColumn, viewGenomeButtonsColumn, layout.NewSpacer()) page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), traitNameRow, widget.NewSeparator(), genomePairRow, widget.NewSeparator(), genomesGrid) setPageContent(page, window) } // This function provides a page to view the couple offspring rule probabilities for a particular genome pair func setViewCoupleTraitRulesPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, traitName string, genomePairIdentifier [32]byte, genomePairName string, previousPage func()){ setLoadingScreen(window, "Loading Trait Rules", "Loading trait rules...") currentPage := func(){setViewCoupleTraitRulesPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, traitName, genomePairIdentifier, genomePairName, previousPage)} title := getPageTitleCentered("View Offspring Trait Rules - " + traitName) backButton := getBackButtonCentered(previousPage) description1 := widget.NewLabel("Below are the trait rule probabilities for offspring from this genome pair.") traitRulesHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringTraitRulesExplainerPage(window, currentPage) }) description1Row := container.NewHBox(layout.NewSpacer(), description1, traitRulesHelpButton, layout.NewSpacer()) genomePairLabel := widget.NewLabel("Genome Pair:") genomePairNameLabel := getBoldLabel(genomePairName) viewGenomePairInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewCoupleGeneticAnalysisTraitGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, traitName, genomePairIdentifier, genomePairName, currentPage) }) genomePairRow := container.NewHBox(layout.NewSpacer(), genomePairLabel, genomePairNameLabel, viewGenomePairInfoButton, layout.NewSpacer()) _, _, numberOfRulesTested, _, err := readGeneticAnalysis.GetOffspringTraitInfoFromGeneticAnalysis(coupleAnalysisObject, traitName, genomePairIdentifier) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } numberOfRulesTestedString := helpers.ConvertIntToString(numberOfRulesTested) traitRulesMap, err := traits.GetTraitRulesMap(traitName) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } totalNumberOfRules := len(traitRulesMap) totalNumberOfRulesString := helpers.ConvertIntToString(totalNumberOfRules) rulesTestedLabel := widget.NewLabel("Rules Tested:") rulesTestedText := getBoldLabel(numberOfRulesTestedString + "/" + totalNumberOfRulesString) rulesTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringTraitNumberOfRulesTestedExplainerPage(window, currentPage) }) rulesTestedRow := container.NewHBox(layout.NewSpacer(), rulesTestedLabel, rulesTestedText, rulesTestedHelpButton, layout.NewSpacer()) getRulesGrid := func()(*fyne.Container, error){ emptyLabelA := widget.NewLabel("") ruleIdentifierLabel := getItalicLabelCentered("Rule Identifier") emptyLabelB := widget.NewLabel("") ruleEffectsLabel := getItalicLabelCentered("Rule Effects") offspringProbabilityOfLabel := getItalicLabelCentered("Offspring Probability Of") passingRuleLabel := getItalicLabelCentered("Passing Rule") emptyLabelC := widget.NewLabel("") emptyLabelD := widget.NewLabel("") ruleIdentifierColumn := container.NewVBox(emptyLabelA, ruleIdentifierLabel, widget.NewSeparator()) ruleEffectsColumn := container.NewVBox(emptyLabelB, ruleEffectsLabel, widget.NewSeparator()) offspringProbabilityOfPassingRuleColumn := container.NewVBox(offspringProbabilityOfLabel, passingRuleLabel, widget.NewSeparator()) ruleInfoButtonsColumn := container.NewVBox(emptyLabelC, emptyLabelD, widget.NewSeparator()) addRuleRow := func(ruleIdentifierHex string)error{ ruleIdentifierLabel := getBoldLabelCentered(ruleIdentifierHex) ruleIdentifier, err := encoding.DecodeHexStringTo3ByteArray(ruleIdentifierHex) if (err != nil) { return err } offspringRuleProbabilityKnown, _, offspringProbabilityOfPassingRuleFormatted, err := readGeneticAnalysis.GetOffspringTraitRuleInfoFromGeneticAnalysis(coupleAnalysisObject, traitName, ruleIdentifier, genomePairIdentifier) if (err != nil) { return err } viewRuleDetailsButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewCoupleGeneticAnalysisTraitRuleDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, traitName, ruleIdentifier, currentPage) }) getProbabilityOfPassingRuleText := func()string{ if (offspringRuleProbabilityKnown == false){ result := translate("Unknown") return result } return offspringProbabilityOfPassingRuleFormatted } probabilityOfPassingRuleText := getProbabilityOfPassingRuleText() probabilityOfPassingRuleTextLabel := getBoldLabelCentered(probabilityOfPassingRuleText) // 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 ruleIdentifierColumn.Add(ruleIdentifierLabel) offspringProbabilityOfPassingRuleColumn.Add(probabilityOfPassingRuleTextLabel) ruleInfoButtonsColumn.Add(viewRuleDetailsButton) traitRuleObject, exists := traitRulesMap[ruleIdentifierHex] if (exists == false){ return errors.New("Trait rule not found after being found already: " + ruleIdentifierHex) } 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{ outcomeChange, exists := ruleOutcomePointsMap[outcomeName] if (exists == false){ return errors.New("OutcomeName not found in ruleOutcomePointsMap after being found already: " + outcomeName) } getOutcomeEffectString := func()string{ outcomeChangeString := helpers.ConvertIntToString(outcomeChange) if (outcomeChange < 0){ return outcomeChangeString } outcomeEffect := "+" + outcomeChangeString 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) offspringProbabilityOfPassingRuleColumn.Add(emptyLabelB) ruleInfoButtonsColumn.Add(emptyLabelC) } } ruleIdentifierColumn.Add(widget.NewSeparator()) ruleEffectsColumn.Add(widget.NewSeparator()) offspringProbabilityOfPassingRuleColumn.Add(widget.NewSeparator()) ruleInfoButtonsColumn.Add(widget.NewSeparator()) return nil } rulesWithKnownProbabilityList := make([]string, 0) rulesWithUnknownProbabilityList := make([]string, 0) for ruleIdentifierHex, _ := range traitRulesMap{ ruleIdentifier, err := encoding.DecodeHexStringTo3ByteArray(ruleIdentifierHex) if (err != nil) { return nil, err } offspringRuleProbabilityKnown, _, _, err := readGeneticAnalysis.GetOffspringTraitRuleInfoFromGeneticAnalysis(coupleAnalysisObject, traitName, ruleIdentifier, genomePairIdentifier) if (err != nil) { return nil, err } if (offspringRuleProbabilityKnown == true){ rulesWithKnownProbabilityList = append(rulesWithKnownProbabilityList, ruleIdentifierHex) } else { rulesWithUnknownProbabilityList = append(rulesWithUnknownProbabilityList, ruleIdentifierHex) } } // Now we sort rules so they show up in the same order each time helpers.SortStringListToUnicodeOrder(rulesWithKnownProbabilityList) helpers.SortStringListToUnicodeOrder(rulesWithUnknownProbabilityList) for _, ruleIdentifier := range rulesWithKnownProbabilityList{ err = addRuleRow(ruleIdentifier) if (err != nil) { return nil, err } } for _, ruleIdentifier := range rulesWithUnknownProbabilityList{ err = addRuleRow(ruleIdentifier) if (err != nil) { return nil, err } } ruleEffectsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setTraitRuleOutcomeEffectsExplainerPage(window, currentPage) }) ruleEffectsColumn.Add(ruleEffectsHelpButton) offspringProbabilityOfPassingRuleHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){ setOffspringProbabilityOfPassingTraitRuleExplainerPage(window, currentPage) }) offspringProbabilityOfPassingRuleColumn.Add(offspringProbabilityOfPassingRuleHelpButton) rulesGrid := container.NewHBox(layout.NewSpacer(), ruleIdentifierColumn, ruleEffectsColumn, offspringProbabilityOfPassingRuleColumn, ruleInfoButtonsColumn, layout.NewSpacer()) return rulesGrid, nil } rulesGrid, err := getRulesGrid() if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } page := container.NewVBox(title, backButton, widget.NewSeparator(), description1Row, widget.NewSeparator(), genomePairRow, widget.NewSeparator(), rulesTestedRow, widget.NewSeparator(), rulesGrid) setPageContent(page, window) } // This function implements a page to view the details of a specific rule from a genetic analysis // It will show the rule details for all of the couple's genome pairs func setViewCoupleGeneticAnalysisTraitRuleDetailsPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, traitName string, ruleIdentifier [3]byte, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisTraitRuleDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, traitName, ruleIdentifier, previousPage)} title := getPageTitleCentered("Trait Rule Details - " + traitName) backButton := getBackButtonCentered(previousPage) description := getLabelCentered("Below is the trait rule analysis for the couple.") ruleIdentifierHex := encoding.EncodeBytesToHexString(ruleIdentifier[:]) ruleIdentifierLabel := widget.NewLabel("Rule Identifier:") ruleIdentifierText := getBoldLabel(ruleIdentifierHex) ruleInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewTraitRuleDetailsPage(window, traitName, ruleIdentifierHex, currentPage) }) ruleIdentifierRow := container.NewHBox(layout.NewSpacer(), ruleIdentifierLabel, ruleIdentifierText, ruleInfoButton, layout.NewSpacer()) getGenomePairsRuleInfoGrid := func()(*fyne.Container, error){ emptyLabelA := widget.NewLabel("") emptyLabelB := widget.NewLabel("") emptyLabelC := widget.NewLabel("") genomePairLabel := getItalicLabelCentered("Genome Pair") offspringProbabilityOfLabel := getItalicLabelCentered("Offspring Probability Of") passingRuleLabel := getItalicLabelCentered("Passing Rule") viewGenomePairInfoButtonsColumn := container.NewVBox(emptyLabelA, emptyLabelB, widget.NewSeparator()) genomePairNameColumn := container.NewVBox(emptyLabelC, genomePairLabel, widget.NewSeparator()) offspringProbabilityOfPassingRuleColumn := container.NewVBox(offspringProbabilityOfLabel, passingRuleLabel, widget.NewSeparator()) addGenomePairRow := func(genomePairName string, genomePairIdentifier [32]byte)error{ offspringRuleProbabilityKnown, _, offspringProbabilityOfPassingRuleFormatted, err := readGeneticAnalysis.GetOffspringTraitRuleInfoFromGeneticAnalysis(coupleAnalysisObject, traitName, ruleIdentifier, genomePairIdentifier) if (err != nil) { return err } getOffspringProbabilityOfPassingRuleText := func()string{ if (offspringRuleProbabilityKnown == false){ result := translate("Unknown") return result } return offspringProbabilityOfPassingRuleFormatted } offspringProbabilityOfPassingRuleText := getOffspringProbabilityOfPassingRuleText() viewGenomePairInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewCoupleGeneticAnalysisTraitGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, traitName, genomePairIdentifier, genomePairName, currentPage) }) genomePairNameLabel := getBoldLabelCentered(genomePairName) offspringProbabilityOfPassingRuleLabel := getBoldLabelCentered(offspringProbabilityOfPassingRuleText) viewGenomePairInfoButtonsColumn.Add(viewGenomePairInfoButton) genomePairNameColumn.Add(genomePairNameLabel) offspringProbabilityOfPassingRuleColumn.Add(offspringProbabilityOfPassingRuleLabel) viewGenomePairInfoButtonsColumn.Add(widget.NewSeparator()) genomePairNameColumn.Add(widget.NewSeparator()) offspringProbabilityOfPassingRuleColumn.Add(widget.NewSeparator()) return nil } pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier, secondGenomePairExists, pair2Person1GenomeIdentifier, pair2Person2GenomeIdentifier, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisObject) if (err != nil){ return nil, err } genomePair1Identifier := helpers.JoinTwo16ByteArrays(pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier) err = addGenomePairRow("Pair 1", genomePair1Identifier) if (err != nil) { return nil, err } if (secondGenomePairExists == true){ genomePair2Identifier := helpers.JoinTwo16ByteArrays(pair2Person1GenomeIdentifier, pair2Person2GenomeIdentifier) err := addGenomePairRow("Pair 2", genomePair2Identifier) if (err != nil) { return nil, err } } genomesContainer := container.NewHBox(layout.NewSpacer(), viewGenomePairInfoButtonsColumn, genomePairNameColumn, offspringProbabilityOfPassingRuleColumn, layout.NewSpacer()) return genomesContainer, nil } genomePairsRuleInfoGrid, err := getGenomePairsRuleInfoGrid() if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), ruleIdentifierRow, widget.NewSeparator(), genomePairsRuleInfoGrid) setPageContent(page, window) }