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 "seekia/resources/geneticReferences/monogenicDiseases" import "seekia/resources/geneticReferences/polygenicDiseases" import "seekia/resources/geneticReferences/traits" import "seekia/internal/appMemory" import "seekia/internal/genetics/myGenomes" import "seekia/internal/genetics/myPeople" import "seekia/internal/genetics/readGeneticAnalysis" import "seekia/internal/helpers" import "strings" import "errors" func setViewCoupleGeneticAnalysisPage(window fyne.Window, personAIdentifier string, personBIdentifier string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, numberOfPersonAGenomesAnalyzed int, numberOfPersonBGenomesAnalyzed int, previousPage func()){ appMemory.SetMemoryEntry("CurrentViewedPage", "ViewCoupleGeneticAnalysisPage") currentPage := func(){setViewCoupleGeneticAnalysisPage(window, personAIdentifier, personBIdentifier, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, numberOfPersonAGenomesAnalyzed, numberOfPersonBGenomesAnalyzed, previousPage)} title := getPageTitleCentered("Viewing Genetic Analysis") backButton := getBackButtonCentered(previousPage) warningLabel := getBoldLabelCentered("WARNING: Results are not accurate!") personAFound, personAName, _, _, err := myPeople.GetPersonInfo(personAIdentifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } if (personAFound == false){ setErrorEncounteredPage(window, errors.New("Couple person A not found."), previousPage) return } personBFound, personBName, _, _, err := myPeople.GetPersonInfo(personBIdentifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } if (personBFound == false){ setErrorEncounteredPage(window, errors.New("Couple person B not found."), previousPage) return } coupleNameLabel := widget.NewLabel("Couple Name:") coupleNameText := getBoldLabel(personAName + " + " + personBName) coupleNameRow := container.NewHBox(layout.NewSpacer(), coupleNameLabel, coupleNameText, layout.NewSpacer()) numberOfAnalyzedGenomesLabel := getLabelCentered("Number of Analyzed Genomes:") personANameLabel := widget.NewLabel(personAName + ":") personANumberOfGenomesAnalyzedString := helpers.ConvertIntToString(numberOfPersonAGenomesAnalyzed) personANumberOfGenomesAnalyzedLabel := getBoldLabel(personANumberOfGenomesAnalyzedString) personANumberOfAnalyzedGenomesRow := container.NewHBox(layout.NewSpacer(), personANameLabel, personANumberOfGenomesAnalyzedLabel, layout.NewSpacer()) personBNameLabel := widget.NewLabel(personBName + ":") personBNumberOfGenomesAnalyzedString := helpers.ConvertIntToString(numberOfPersonBGenomesAnalyzed) personBNumberOfGenomesAnalyzedLabel := getBoldLabel(personBNumberOfGenomesAnalyzedString) personBNumberOfAnalyzedGenomesRow := container.NewHBox(layout.NewSpacer(), personBNameLabel, personBNumberOfGenomesAnalyzedLabel, 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, currentPage) }) polygenicDiseasesButton := widget.NewButton("Polygenic Diseases", func(){ setViewCoupleGeneticAnalysisPolygenicDiseasesPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, currentPage) }) traitsButton := widget.NewButton("Traits", func(){ setViewCoupleGeneticAnalysisTraitsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, currentPage) }) categoryButtonsGrid := getContainerCentered(container.NewGridWithColumns(1, generalButton, monogenicDiseasesButton, polygenicDiseasesButton, traitsButton)) page := container.NewVBox(title, backButton, widget.NewSeparator(), warningLabel, widget.NewSeparator(), coupleNameRow, widget.NewSeparator(), numberOfAnalyzedGenomesLabel, personANumberOfAnalyzedGenomesRow, personBNumberOfAnalyzedGenomesRow, widget.NewSeparator(), categoryButtonsGrid) setPageContent(page, window) } func setViewCoupleGeneticAnalysisMonogenicDiseasesPage(window fyne.Window, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisMonogenicDiseasesPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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){ pair1PersonAGenomeIdentifier, pair1PersonBGenomeIdentifier, secondGenomePairExists, _, _, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisMapList) 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{ pair1GenomeIdentifier := pair1PersonAGenomeIdentifier + "+" + pair1PersonBGenomeIdentifier genomeProbabilitiesKnown, _, genomePairOffspringProbabilityOfHavingDisease, _, _, conflictExists, err := readGeneticAnalysis.GetOffspringMonogenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisMapList, diseaseName, pair1GenomeIdentifier, secondGenomePairExists) if (err != nil) { return nil, err } getOffspringProbabilityOfHavingDiseaseText := func()string{ if (genomeProbabilitiesKnown == 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, diseaseName string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisMonogenicDiseaseDetailsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, diseaseName, previousPage)} title := getPageTitleCentered("Viewing Couple Analysis - " + diseaseName) backButton := getBackButtonCentered(previousPage) pair1PersonAGenomeIdentifier, pair1PersonBGenomeIdentifier, secondGenomePairExists, pair2PersonAGenomeIdentifier, pair2PersonBGenomeIdentifier, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisMapList) 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, personAGenomeIdentifier string, personBGenomeIdentifier string)error{ genomePairIdentifier := personAGenomeIdentifier + "+" + personBGenomeIdentifier genomeProbabilitiesKnown, _, genomePairOffspringProbabilityOfHavingDisease, _, genomePairOffspringProbabilityOfHavingAVariant, _, err := readGeneticAnalysis.GetOffspringMonogenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisMapList, diseaseName, genomePairIdentifier, secondGenomePairExists) if (err != nil) { return err } getOffspringProbabilityOfHavingDiseaseText := func()string{ if (genomeProbabilitiesKnown == false){ result := translate("Unknown") return result } return genomePairOffspringProbabilityOfHavingDisease } offspringProbabilityOfHavingDiseaseText := getOffspringProbabilityOfHavingDiseaseText() getOffspringProbabilityOfHavingAVariantText := func()string{ if (genomeProbabilitiesKnown == 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, diseaseName, genomePairIdentifier, genomePairName, currentPage) }) viewOffspringVariantsButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewCoupleMonogenicDiseaseVariantsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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", pair1PersonAGenomeIdentifier, pair1PersonBGenomeIdentifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } if (secondGenomePairExists == true){ err := addGenomePairRow("Pair 2", pair2PersonAGenomeIdentifier, pair2PersonBGenomeIdentifier) 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, diseaseName string, genomePairIdentifier string, genomePairName string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisMonogenicDiseaseGenomePairDetailsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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()) 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(isPersonA bool, personName string, inputGenomeIdentifier string)error{ personAnalysisGenomeIdentifier, personHasMultipleGenomes, genomeIsCombined, combinedType, err := readGeneticAnalysis.GetMatchingPersonAnalysisGenomeIdentifierFromCoupleAnalysis(isPersonA, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, inputGenomeIdentifier) if (err != nil) { return err } personNameTrimmed, _, err := helpers.TrimAndFlattenString(personName, 10) if (err != nil) { return err } personNameLabel := getBoldLabelCentered(personNameTrimmed) getPersonAnalysisMapList := func()[]map[string]string{ if (isPersonA == true){ return personAAnalysisMapList } return personBAnalysisMapList } personAnalysisMapList := getPersonAnalysisMapList() 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 analysisMapList 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(personAnalysisMapList, diseaseName, personAnalysisGenomeIdentifier, personHasMultipleGenomes) 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) viewGenomeButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewPersonGenomeMonogenicDiseaseVariantsPage(window, personAnalysisMapList, 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 } personAGenomeIdentifier, personBGenomeIdentifier, found := strings.Cut(genomePairIdentifier, "+") if (found == false){ setErrorEncounteredPage(window, errors.New("setViewCoupleGeneticAnalysisMonogenicDiseaseGenomePairDetailsPage called with invalid genomePairIdentifier"), previousPage) return } err := addGenomeRow(true, personAName, personAGenomeIdentifier) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } err = addGenomeRow(false, personBName, personBGenomeIdentifier) 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, diseaseName string, genomePairIdentifier string, genomePairName string, previousPage func()){ setLoadingScreen(window, "Loading Disease Variants", "Loading disease variants...") currentPage := func(){setViewCoupleMonogenicDiseaseVariantsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, diseaseName, genomePairIdentifier, genomePairName, currentPage) }) genomePairRow := container.NewHBox(layout.NewSpacer(), genomePairLabel, genomePairNameLabel, viewGenomePairInfoButton, layout.NewSpacer()) getNumberOfVariantsTested := func()(int, error){ personAGenomeIdentifier, personBGenomeIdentifier, found := strings.Cut(genomePairIdentifier, "+") if (found == false){ return 0, errors.New("setViewCoupleMonogenicDiseaseVariantsPage called with invalid genomePairIdentifier: " + genomePairIdentifier) } personAAnalysisGenomeIdentifier, personAHasMultipleGenomes, _, _, err := readGeneticAnalysis.GetMatchingPersonAnalysisGenomeIdentifierFromCoupleAnalysis(true, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, personAGenomeIdentifier) if (err != nil) { return 0, err } _, _, _, _, _, personANumberOfVariantsTested, _, err := readGeneticAnalysis.GetPersonMonogenicDiseaseInfoFromGeneticAnalysis(personAAnalysisMapList, diseaseName, personAAnalysisGenomeIdentifier, personAHasMultipleGenomes) if (err != nil) { return 0, err } personBAnalysisGenomeIdentifier, personBHasMultipleGenomes, _, _, err := readGeneticAnalysis.GetMatchingPersonAnalysisGenomeIdentifierFromCoupleAnalysis(false, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, personBGenomeIdentifier) if (err != nil) { return 0, err } _, _, _, _, _, personBNumberOfVariantsTested, _, err := readGeneticAnalysis.GetPersonMonogenicDiseaseInfoFromGeneticAnalysis(personBAnalysisMapList, diseaseName, personBAnalysisGenomeIdentifier, personBHasMultipleGenomes) if (err != nil) { return 0, err } numberOfVariantsTested := personANumberOfVariantsTested + personBNumberOfVariantsTested return numberOfVariantsTested, nil } numberOfVariantsTested, err := getNumberOfVariantsTested() 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()) //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(variantIdentifier string)error{ variantObject, exists := diseaseVariantsMap[variantIdentifier] if (exists == false){ return errors.New("Cannot add variant row: Variant missing from diseaseVariantsMap") } variantName := variantObject.VariantNames[0] offspringProbabilitiesKnown, probabilityOf0MutationsLowerBound, probabilityOf0MutationsUpperBound, probabilityOf0MutationsFormatted, probabilityOf1MutationLowerBound, probabilityOf1MutationUpperBound, probabilityOf1MutationFormatted, probabilityOf2MutationsLowerBound, probabilityOf2MutationsUpperBound, probabilityOf2MutationsFormatted, err := readGeneticAnalysis.GetOffspringMonogenicDiseaseVariantInfoFromGeneticAnalysis(coupleAnalysisMapList, 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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 variantIdentifier, _ := range diseaseVariantsMap{ probabilitesKnown, probabilityOf0MutationsLowerBound, probabilityOf0MutationsUpperBound, _, probabilityOf1MutationLowerBound, probabilityOf1MutationUpperBound, _, probabilityOf2MutationsLowerBound, probabilityOf2MutationsUpperBound, _, err := readGeneticAnalysis.GetOffspringMonogenicDiseaseVariantInfoFromGeneticAnalysis(coupleAnalysisMapList, diseaseName, variantIdentifier, genomePairIdentifier) if (err != nil) { return nil, err } if (probabilitesKnown == false){ variantsWithUnknownRiskList = append(variantsWithUnknownRiskList, variantIdentifier) continue } if (probabilityOf1MutationLowerBound != 0 || probabilityOf2MutationsLowerBound != 0){ variantsWithNonZeroRiskList = append(variantsWithNonZeroRiskList, variantIdentifier) continue } // Risk is either 0 or partially unknown if (probabilityOf0MutationsLowerBound == 100 && probabilityOf0MutationsUpperBound == 100 && probabilityOf1MutationLowerBound == 0 && probabilityOf1MutationUpperBound == 0 && probabilityOf2MutationsLowerBound == 0 && probabilityOf2MutationsUpperBound == 0){ variantsWithZeroRiskFullyKnownList = append(variantsWithZeroRiskFullyKnownList, variantIdentifier) continue } variantsWithZeroRiskPartiallyKnownList = append(variantsWithZeroRiskPartiallyKnownList, variantIdentifier) } // 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(), 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, diseaseName string, variantIdentifier string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisMonogenicDiseaseVariantDetailsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, diseaseName, variantIdentifier, previousPage)} title := getPageTitleCentered("Disease Variant Details - " + diseaseName) backButton := getBackButtonCentered(previousPage) variantObject, err := monogenicDiseases.GetMonogenicDiseaseVariantObject(diseaseName, variantIdentifier) 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, variantIdentifier, 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 string)error{ probabilitiesKnown, probabilityOf0MutationsLowerBound, probabilityOf0MutationsUpperBound, probabilityOf0MutationsFormatted, probabilityOf1MutationLowerBound, probabilityOf1MutationUpperBound, probabilityOf1MutationFormatted, probabilityOf2MutationsLowerBound, probabilityOf2MutationsUpperBound, probabilityOf2MutationsFormatted, err := readGeneticAnalysis.GetOffspringMonogenicDiseaseVariantInfoFromGeneticAnalysis(coupleAnalysisMapList, 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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 } pair1PersonAGenomeIdentifier, pair1PersonBGenomeIdentifier, secondGenomePairExists, pair2PersonAGenomeIdentifier, pair2PersonBGenomeIdentifier, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisMapList) if (err != nil){ return nil, err } genomePair1Identifier := pair1PersonAGenomeIdentifier + "+" + pair1PersonBGenomeIdentifier err = addGenomePairRow("Pair 1", genomePair1Identifier) if (err != nil) { return nil, err } if (secondGenomePairExists == true){ genomePair2Identifier := pair2PersonAGenomeIdentifier + "+" + pair2PersonBGenomeIdentifier 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisPolygenicDiseasesPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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){ pair1PersonAGenomeIdentifier, pair1PersonBGenomeIdentifier, secondGenomePairExists, _, _, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisMapList) 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 := pair1PersonAGenomeIdentifier + "+" + pair1PersonBGenomeIdentifier offspringRiskScoreKnown, _, offspringRiskScoreFormatted, _, conflictExists, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisMapList, diseaseName, mainGenomePairIdentifier, secondGenomePairExists) 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, diseaseName string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisPolygenicDiseaseDetailsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, diseaseName, previousPage)} title := getPageTitleCentered("Viewing Couple Analysis - " + diseaseName) backButton := getBackButtonCentered(previousPage) pair1PersonAGenomeIdentifier, pair1PersonBGenomeIdentifier, secondGenomePairExists, pair2PersonAGenomeIdentifier, pair2PersonBGenomeIdentifier, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisMapList) 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()) emptyLabelA := widget.NewLabel("") emptyLabelB := widget.NewLabel("") offspringRiskScoreLabel := getItalicLabelCentered("Offspring Risk Score") emptyLabelC := widget.NewLabel("") emptyLabelD := widget.NewLabel("") viewGenomePairButtonsColumn := container.NewVBox(emptyLabelA, widget.NewSeparator()) pairNameColumn := container.NewVBox(emptyLabelB, widget.NewSeparator()) offspringRiskScoreColumn := container.NewVBox(offspringRiskScoreLabel, widget.NewSeparator()) viewLifetimeRiskButtonsColumn := container.NewVBox(emptyLabelC, widget.NewSeparator()) viewOffspringLociButtonsColumn := container.NewVBox(emptyLabelD, widget.NewSeparator()) addGenomePairRow := func(genomePairName string, personAGenomeIdentifier string, personBGenomeIdentifier string)error{ genomePairIdentifier := personAGenomeIdentifier + "+" + personBGenomeIdentifier offspringRiskScoreKnown, _, offspringRiskScoreFormatted, _, _, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisMapList, diseaseName, genomePairIdentifier, secondGenomePairExists) 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, diseaseName, genomePairIdentifier, genomePairName, 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, diseaseName, genomePairIdentifier, genomePairName, currentPage) }) viewGenomePairButtonsColumn.Add(viewGenomePairButton) pairNameColumn.Add(genomePairNameLabel) offspringRiskScoreColumn.Add(offspringRiskScoreLabel) viewLifetimeRiskButtonsColumn.Add(viewOffspringLifetimeRiskButton) viewOffspringLociButtonsColumn.Add(viewOffspringLociButton) viewGenomePairButtonsColumn.Add(widget.NewSeparator()) pairNameColumn.Add(widget.NewSeparator()) offspringRiskScoreColumn.Add(widget.NewSeparator()) viewOffspringLociButtonsColumn.Add(widget.NewSeparator()) return nil } err = addGenomePairRow("Pair 1", pair1PersonAGenomeIdentifier, pair1PersonBGenomeIdentifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } if (secondGenomePairExists == true){ err := addGenomePairRow("Pair 2", pair2PersonAGenomeIdentifier, pair2PersonBGenomeIdentifier) 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, 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, diseaseName string, genomePairIdentifier string, genomePairName string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisPolygenicDiseaseGenomePairDetailsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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(isPersonA bool, personName string, inputGenomeIdentifier string)error{ personAnalysisGenomeIdentifier, personHasMultipleGenomes, genomeIsCombined, combinedType, err := readGeneticAnalysis.GetMatchingPersonAnalysisGenomeIdentifierFromCoupleAnalysis(isPersonA, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, inputGenomeIdentifier) if (err != nil) { return err } personNameTrimmed, _, err := helpers.TrimAndFlattenString(personName, 10) if (err != nil) { return err } personNameLabel := getBoldLabelCentered(personNameTrimmed) getPersonAnalysisMapList := func()[]map[string]string{ if (isPersonA == true){ return personAAnalysisMapList } return personBAnalysisMapList } personAnalysisMapList := getPersonAnalysisMapList() 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 analysisMapList 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(personAnalysisMapList, diseaseName, personAnalysisGenomeIdentifier, personHasMultipleGenomes) 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, personAnalysisMapList, 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 } personAGenomeIdentifier, personBGenomeIdentifier, found := strings.Cut(genomePairIdentifier, "+") if (found == false){ setErrorEncounteredPage(window, errors.New("setViewCoupleGeneticAnalysisPolygenicDiseaseGenomePairDetailsPage called with invalid genomePairIdentifier"), previousPage) return } err := addGenomeRow(true, personAName, personAGenomeIdentifier) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } err = addGenomeRow(false, personBName, personBGenomeIdentifier) 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, diseaseName string, genomePairIdentifier string, genomePairName string, previousPage func()){ setLoadingScreen(window, "Loading Polygenic Disease Loci", "Loading disease loci...") currentPage := func(){setViewCouplePolygenicDiseaseLociPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, diseaseName, genomePairIdentifier, genomePairName, currentPage) }) genomePairRow := container.NewHBox(layout.NewSpacer(), genomePairLabel, genomePairNameLabel, viewGenomePairInfoButton, layout.NewSpacer()) _, _, secondGenomePairExists, _, _, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisMapList) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } _, _, _, numberOfLociTested, _, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisMapList, diseaseName, genomePairIdentifier, secondGenomePairExists) 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(locusIdentifier string)error{ locusObject, exists := diseaseLociMap[locusIdentifier] if (exists == false) { return errors.New("Cannot add locus row: Locus not found in diseaseLociMap: " + locusIdentifier) } locusRSID := locusObject.LocusRSID locusRSIDString := helpers.ConvertInt64ToString(locusRSID) locusName := "rs" + locusRSIDString offspringRiskWeightKnown, offspringRiskWeight, offspringOddsRatioKnown, _, offspringOddsRatioFormatted, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseLocusInfoFromGeneticAnalysis(coupleAnalysisMapList, 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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 locusIdentifier, _ := range diseaseLociMap{ offspringRiskWeightKnown, _, _, _, _, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseLocusInfoFromGeneticAnalysis(coupleAnalysisMapList, diseaseName, locusIdentifier, genomePairIdentifier) if (err != nil) { return nil, err } if (offspringRiskWeightKnown == true){ lociWithKnownRiskWeightList = append(lociWithKnownRiskWeightList, locusIdentifier) } else { lociWithUnknownRiskWeightList = append(lociWithUnknownRiskWeightList, locusIdentifier) } } // 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, diseaseName string, locusIdentifier string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisPolygenicDiseaseLocusDetailsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, diseaseName, locusIdentifier, previousPage)} title := getPageTitleCentered("Disease Locus Details - " + diseaseName) backButton := getBackButtonCentered(previousPage) locusObject, err := polygenicDiseases.GetPolygenicDiseaseLocusObject(diseaseName, locusIdentifier) 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, locusIdentifier, 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 string)error{ offspringRiskWeightKnown, offspringRiskWeight, offspringOddsRatioKnown, _, offspringOddsRatioFormatted, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseLocusInfoFromGeneticAnalysis(coupleAnalysisMapList, 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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 } pair1PersonAGenomeIdentifier, pair1PersonBGenomeIdentifier, secondGenomePairExists, pair2PersonAGenomeIdentifier, pair2PersonBGenomeIdentifier, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisMapList) if (err != nil){ return nil, err } genomePair1Identifier := pair1PersonAGenomeIdentifier + "+" + pair1PersonBGenomeIdentifier err = addGenomePairRow("Pair 1", genomePair1Identifier) if (err != nil) { return nil, err } if (secondGenomePairExists == true){ genomePair2Identifier := pair2PersonAGenomeIdentifier + "+" + pair2PersonBGenomeIdentifier 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) } func setViewCoupleGeneticAnalysisTraitsPage(window fyne.Window, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisTraitsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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){ pair1PersonAGenomeIdentifier, pair1PersonBGenomeIdentifier, secondGenomePairExists, _, _, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisMapList) 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 := pair1PersonAGenomeIdentifier + "+" + pair1PersonBGenomeIdentifier offspringOutcomeScoresKnown, offspringAverageOutcomeScoresMap, _, conflictExists, err := readGeneticAnalysis.GetOffspringTraitInfoFromGeneticAnalysis(coupleAnalysisMapList, traitName, mainGenomePairIdentifier, secondGenomePairExists) 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, traitName, previousPage) })) 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, traitName string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisTraitDetailsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, traitName, previousPage)} title := getPageTitleCentered("Viewing Couple Analysis - " + traitName) backButton := getBackButtonCentered(previousPage) pair1PersonAGenomeIdentifier, pair1PersonBGenomeIdentifier, secondGenomePairExists, pair2PersonAGenomeIdentifier, pair2PersonBGenomeIdentifier, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisMapList) 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, personAGenomeIdentifier string, personBGenomeIdentifier string)error{ genomePairIdentifier := personAGenomeIdentifier + "+" + personBGenomeIdentifier genomePairNameLabel := getBoldLabelCentered(genomePairName) viewGenomePairButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewCoupleGeneticAnalysisTraitGenomePairDetailsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, traitName, genomePairIdentifier, genomePairName, currentPage) }) viewOffspringRulesButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewCoupleTraitRulesPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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(coupleAnalysisMapList, traitName, genomePairIdentifier, secondGenomePairExists) 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", pair1PersonAGenomeIdentifier, pair1PersonBGenomeIdentifier) if (err != nil) { setErrorEncounteredPage(window, err, previousPage) return } if (secondGenomePairExists == true){ err := addGenomePairRow("Pair 2", pair2PersonAGenomeIdentifier, pair2PersonBGenomeIdentifier) 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, traitName string, genomePairIdentifier string, genomePairName string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisTraitGenomePairDetailsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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(isPersonA bool, personName string, inputGenomeIdentifier string)error{ personAnalysisGenomeIdentifier, personHasMultipleGenomes, genomeIsCombined, combinedType, err := readGeneticAnalysis.GetMatchingPersonAnalysisGenomeIdentifierFromCoupleAnalysis(isPersonA, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, inputGenomeIdentifier) if (err != nil) { return err } personNameTrimmed, _, err := helpers.TrimAndFlattenString(personName, 10) if (err != nil) { return err } personNameLabel := getBoldLabelCentered(personNameTrimmed) getPersonAnalysisMapList := func()[]map[string]string{ if (isPersonA == true){ return personAAnalysisMapList } return personBAnalysisMapList } personAnalysisMapList := getPersonAnalysisMapList() 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 analysisMapList 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(personAnalysisMapList, traitName, personAnalysisGenomeIdentifier, personHasMultipleGenomes) if (err != nil) { return err } numberOfRulesTestedString := helpers.ConvertIntToString(numberOfRulesTested) numberOfRulesTestedText := getBoldLabelCentered(numberOfRulesTestedString) viewGenomeButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewPersonGenomeTraitRulesPage(window, personAnalysisMapList, 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 } personAGenomeIdentifier, personBGenomeIdentifier, found := strings.Cut(genomePairIdentifier, "+") if (found == false){ setErrorEncounteredPage(window, errors.New("setViewCoupleGeneticAnalysisTraitGenomePairDetailsPage called with invalid genomePairIdentifier"), previousPage) return } err := addGenomeRow(true, personAName, personAGenomeIdentifier) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } err = addGenomeRow(false, personBName, personBGenomeIdentifier) 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, traitNameRow, 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, traitName string, genomePairIdentifier string, genomePairName string, previousPage func()){ setLoadingScreen(window, "Loading Trait Rules", "Loading trait rules...") currentPage := func(){setViewCoupleTraitRulesPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, traitName, genomePairIdentifier, genomePairName, currentPage) }) genomePairRow := container.NewHBox(layout.NewSpacer(), genomePairLabel, genomePairNameLabel, viewGenomePairInfoButton, layout.NewSpacer()) _, _, secondGenomePairExists, _, _, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisMapList) if (err != nil){ setErrorEncounteredPage(window, err, previousPage) return } _, _, numberOfRulesTested, _, err := readGeneticAnalysis.GetOffspringTraitInfoFromGeneticAnalysis(coupleAnalysisMapList, traitName, genomePairIdentifier, secondGenomePairExists) 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(ruleIdentifier string)error{ ruleIdentifierLabel := getBoldLabelCentered(ruleIdentifier) offspringRuleProbabilityKnown, _, offspringProbabilityOfPassingRuleFormatted, err := readGeneticAnalysis.GetOffspringTraitRuleInfoFromGeneticAnalysis(coupleAnalysisMapList, traitName, ruleIdentifier, genomePairIdentifier) if (err != nil) { return err } viewRuleDetailsButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){ setViewCoupleGeneticAnalysisTraitRuleDetailsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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[ruleIdentifier] if (exists == false){ return errors.New("Trait rule not found after being found already: " + ruleIdentifier) } 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 ruleIdentifier, _ := range traitRulesMap{ offspringRuleProbabilityKnown, _, _, err := readGeneticAnalysis.GetOffspringTraitRuleInfoFromGeneticAnalysis(coupleAnalysisMapList, traitName, ruleIdentifier, genomePairIdentifier) if (err != nil) { return nil, err } if (offspringRuleProbabilityKnown == true){ rulesWithKnownProbabilityList = append(rulesWithKnownProbabilityList, ruleIdentifier) } else { rulesWithUnknownProbabilityList = append(rulesWithUnknownProbabilityList, ruleIdentifier) } } // 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, personAName string, personBName string, personAAnalysisMapList []map[string]string, personBAnalysisMapList []map[string]string, coupleAnalysisMapList []map[string]string, traitName string, ruleIdentifier string, previousPage func()){ currentPage := func(){setViewCoupleGeneticAnalysisTraitRuleDetailsPage(window, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, traitName, ruleIdentifier, previousPage)} title := getPageTitleCentered("Trait Rule Details - " + traitName) backButton := getBackButtonCentered(previousPage) description := getLabelCentered("Below is the trait rule analysis for the couple.") ruleIdentifierLabel := widget.NewLabel("Rule Identifier:") ruleIdentifierText := getBoldLabel(ruleIdentifier) ruleInfoButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){ setViewTraitRuleDetailsPage(window, traitName, ruleIdentifier, 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 string)error{ offspringRuleProbabilityKnown, _, offspringProbabilityOfPassingRuleFormatted, err := readGeneticAnalysis.GetOffspringTraitRuleInfoFromGeneticAnalysis(coupleAnalysisMapList, 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, personAName, personBName, personAAnalysisMapList, personBAnalysisMapList, coupleAnalysisMapList, 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 } pair1PersonAGenomeIdentifier, pair1PersonBGenomeIdentifier, secondGenomePairExists, pair2PersonAGenomeIdentifier, pair2PersonBGenomeIdentifier, _, _, _, _, _, _, err := readGeneticAnalysis.GetMetadataFromCoupleGeneticAnalysis(coupleAnalysisMapList) if (err != nil){ return nil, err } genomePair1Identifier := pair1PersonAGenomeIdentifier + "+" + pair1PersonBGenomeIdentifier err = addGenomePairRow("Pair 1", genomePair1Identifier) if (err != nil) { return nil, err } if (secondGenomePairExists == true){ genomePair2Identifier := pair2PersonAGenomeIdentifier + "+" + pair2PersonBGenomeIdentifier 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) }