seekia/gui/viewGeneticReferencesGui.go

435 lines
16 KiB
Go
Raw Permalink Normal View History

package gui
// viewGeneticReferencesGui.go implements pages to display information about genetic diseases and traits
import "fyne.io/fyne/v2"
import "fyne.io/fyne/v2/widget"
import "fyne.io/fyne/v2/theme"
import "fyne.io/fyne/v2/container"
import "fyne.io/fyne/v2/layout"
import "seekia/resources/geneticReferences/locusMetadata"
import "seekia/resources/geneticReferences/traits"
import "seekia/resources/geneticReferences/monogenicDiseases"
import "seekia/resources/geneticReferences/polygenicDiseases"
import "seekia/internal/helpers"
import "strings"
import "slices"
import "errors"
func setViewMonogenicDiseaseDetailsPage(window fyne.Window, diseaseName string, previousPage func()){
currentPage := func(){setViewMonogenicDiseaseDetailsPage(window, diseaseName, previousPage)}
title := getPageTitleCentered("Monogenic Disease Details - " + diseaseName)
backButton := getBackButtonCentered(previousPage)
diseaseObject, err := monogenicDiseases.GetMonogenicDiseaseObject(diseaseName)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
diseaseGeneName := diseaseObject.GeneName
diseaseIsDominantOrRecessive := diseaseObject.DominantOrRecessive
diseaseDescription := diseaseObject.DiseaseDescription
diseaseReferencesMap := diseaseObject.References
diseaseNameLabel := widget.NewLabel("Disease Name:")
diseaseNameText := getBoldLabel(diseaseName)
diseaseNameRow := container.NewHBox(layout.NewSpacer(), diseaseNameLabel, diseaseNameText, layout.NewSpacer())
geneNameLabel := widget.NewLabel("Gene Name:")
geneNameText := getBoldLabel(diseaseGeneName)
geneNameRow := container.NewHBox(layout.NewSpacer(), geneNameLabel, geneNameText, layout.NewSpacer())
dominantOrRecessiveLabel := widget.NewLabel("Dominant or Recessive?:")
dominantOrRecessiveText := getBoldLabel(diseaseIsDominantOrRecessive)
dominantOrRecessiveRow := container.NewHBox(layout.NewSpacer(), dominantOrRecessiveLabel, dominantOrRecessiveText, layout.NewSpacer())
diseaseDescriptionTrimmed, _, err := helpers.TrimAndFlattenString(diseaseDescription, 10)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
diseaseDescriptionLabel := widget.NewLabel("Description:")
diseaseDescriptionText := getBoldLabel(diseaseDescriptionTrimmed)
viewDiseaseDescriptionButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
setViewTextPage(window, "Disease Description", diseaseDescription, false, currentPage)
})
diseaseDescriptionRow := container.NewHBox(layout.NewSpacer(), diseaseDescriptionLabel, diseaseDescriptionText, viewDiseaseDescriptionButton, layout.NewSpacer())
viewReferencesButton := getWidgetCentered(widget.NewButtonWithIcon("View References", theme.ListIcon(), func(){
setViewGeneticAnalysisReferencesPage(window, "Monogenic Disease", diseaseReferencesMap, currentPage)
}))
page := container.NewVBox(title, backButton, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), geneNameRow, widget.NewSeparator(), dominantOrRecessiveRow, widget.NewSeparator(), diseaseDescriptionRow, widget.NewSeparator(), viewReferencesButton)
setPageContent(page, window)
}
func setViewMonogenicDiseaseVariantDetailsPage(window fyne.Window, diseaseName string, variantIdentifier string, previousPage func()){
currentPage := func(){setViewMonogenicDiseaseVariantDetailsPage(window, diseaseName, variantIdentifier, previousPage)}
title := getPageTitleCentered("Viewing Monogenic Disease Variant Details")
backButton := getBackButtonCentered(previousPage)
diseaseNameLabel := widget.NewLabel("Disease Name:")
diseaseNameText := getBoldLabel(diseaseName)
diseaseNameRow := container.NewHBox(layout.NewSpacer(), diseaseNameLabel, diseaseNameText, layout.NewSpacer())
variantObject, err := monogenicDiseases.GetMonogenicDiseaseVariantObject(diseaseName, variantIdentifier)
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
variantNamesList := variantObject.VariantNames
nucleotideChange := variantObject.NucleotideChange
aminoAcidChange := variantObject.AminoAcidChange
variantRSID := variantObject.VariantRSID
variantEffectIsMild := variantObject.EffectIsMild
referencesMap := variantObject.References
variantRSIDsList := []int64{variantRSID}
// We add aliases to variantRSIDsList
anyAliasesExist, rsidAliasesList, err := locusMetadata.GetRSIDAliases(variantRSID)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
if (anyAliasesExist == true){
variantRSIDsList = append(variantRSIDsList, rsidAliasesList...)
}
getVariantNamesLabelText := func()string{
if(len(variantNamesList) == 1){
return "Variant Name:"
}
return "Variant Names:"
}
variantNamesLabelText := getVariantNamesLabelText()
variantNamesListString := strings.Join(variantNamesList, ", ")
variantNamesLabel := widget.NewLabel(variantNamesLabelText)
variantNamesText := getBoldLabel(variantNamesListString)
variantNamesRow := container.NewHBox(layout.NewSpacer(), variantNamesLabel, variantNamesText, layout.NewSpacer())
nucleotideChangeLabel := widget.NewLabel("Nucleotide Change:")
nucleotideChangeText := getBoldLabel(nucleotideChange)
nucleotideChangeRow := container.NewHBox(layout.NewSpacer(), nucleotideChangeLabel, nucleotideChangeText, layout.NewSpacer())
page := container.NewVBox(title, backButton, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), variantNamesRow, widget.NewSeparator(), nucleotideChangeRow, widget.NewSeparator())
if (aminoAcidChange != ""){
aminoAcidChangeLabel := widget.NewLabel("Amino Acid Change:")
aminoAcidChangeText := getBoldLabel(aminoAcidChange)
aminoAcidChangeRow := container.NewHBox(layout.NewSpacer(), aminoAcidChangeLabel, aminoAcidChangeText, layout.NewSpacer())
page.Add(aminoAcidChangeRow)
page.Add(widget.NewSeparator())
}
getVariantRSIDsLabelText := func()string{
if (len(variantRSIDsList) == 1){
return "Variant rsID:"
}
return "Variant rsIDs:"
}
variantRSIDsLabelText := getVariantRSIDsLabelText()
variantRSIDStringsList := make([]string, 0, len(variantRSIDsList))
for _, variantRSID := range variantRSIDsList{
variantRSIDString := helpers.ConvertInt64ToString(variantRSID)
variantRSIDName := "rs" + variantRSIDString
variantRSIDStringsList = append(variantRSIDStringsList, variantRSIDName)
}
variantRSIDsListString := strings.Join(variantRSIDStringsList, ", ")
variantRSIDsLabel := widget.NewLabel(variantRSIDsLabelText)
variantRSIDsText := getBoldLabel(variantRSIDsListString)
variantRSIDsRow := container.NewHBox(layout.NewSpacer(), variantRSIDsLabel, variantRSIDsText, layout.NewSpacer())
page.Add(variantRSIDsRow)
page.Add(widget.NewSeparator())
effectIsMildString := helpers.ConvertBoolToYesOrNoString(variantEffectIsMild)
effectIsMildLabel := widget.NewLabel("Effect is Mild:")
effectIsMildText := getBoldLabel(effectIsMildString)
effectIsMildHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setVariantEffectIsMildExplainerPage(window, currentPage)
})
effectIsMildRow := container.NewHBox(layout.NewSpacer(), effectIsMildLabel, effectIsMildText, effectIsMildHelpButton, layout.NewSpacer())
page.Add(effectIsMildRow)
page.Add(widget.NewSeparator())
viewReferencesButton := getWidgetCentered(widget.NewButtonWithIcon("View References", theme.ListIcon(), func(){
setViewGeneticAnalysisReferencesPage(window, "Variant", referencesMap, currentPage)
}))
page.Add(viewReferencesButton)
setPageContent(page, window)
}
func setViewPolygenicDiseaseDetailsPage(window fyne.Window, diseaseName string, previousPage func()){
currentPage := func(){setViewPolygenicDiseaseDetailsPage(window, diseaseName, previousPage)}
title := getPageTitleCentered("Disease Details - " + diseaseName)
backButton := getBackButtonCentered(previousPage)
diseaseObject, err := polygenicDiseases.GetPolygenicDiseaseObject(diseaseName)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
diseaseDescription := diseaseObject.DiseaseDescription
effectedSex := diseaseObject.EffectedSex
diseaseReferencesMap := diseaseObject.References
diseaseNameLabel := widget.NewLabel("Disease Name:")
diseaseNameText := getBoldLabel(diseaseName)
diseaseNameRow := container.NewHBox(layout.NewSpacer(), diseaseNameLabel, diseaseNameText, layout.NewSpacer())
getEffectedSexTextLabelText := func()string{
if (effectedSex == "Both"){
return "Male and Female"
}
return effectedSex
}
effectedSexTextLabelText := getEffectedSexTextLabelText()
effectedSexLabel := widget.NewLabel("Effected Sex:")
effectedSexText := getBoldLabel(effectedSexTextLabelText)
effectedSexRow := container.NewHBox(layout.NewSpacer(), effectedSexLabel, effectedSexText, layout.NewSpacer())
diseaseDescriptionTrimmed, _, err := helpers.TrimAndFlattenString(diseaseDescription, 10)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
diseaseDescriptionLabel := widget.NewLabel("Description:")
diseaseDescriptionText := getBoldLabel(diseaseDescriptionTrimmed)
viewDiseaseDescriptionButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
setViewTextPage(window, "Disease Description", diseaseDescription, false, currentPage)
})
diseaseDescriptionRow := container.NewHBox(layout.NewSpacer(), diseaseDescriptionLabel, diseaseDescriptionText, viewDiseaseDescriptionButton, layout.NewSpacer())
viewReferencesButton := getWidgetCentered(widget.NewButtonWithIcon("View References", theme.ListIcon(), func(){
setViewGeneticAnalysisReferencesPage(window, "Polygenic Disease", diseaseReferencesMap, currentPage)
}))
page := container.NewVBox(title, backButton, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), effectedSexRow, widget.NewSeparator(), diseaseDescriptionRow, widget.NewSeparator(), viewReferencesButton)
setPageContent(page, window)
}
func setViewGeneticAnalysisReferencesPage(window fyne.Window, referencesTopic string, referencesMap map[string]string, previousPage func()){
currentPage := func(){setViewGeneticAnalysisReferencesPage(window, referencesTopic, referencesMap, previousPage)}
pageTitle := "Viewing " + referencesTopic + " References"
title := getPageTitleCentered(pageTitle)
backButton := getBackButtonCentered(previousPage)
referencesContainer := container.NewVBox()
referenceNamesList := helpers.GetListOfMapKeys(referencesMap)
// We sort the references so they always show up in the same order
slices.Sort(referenceNamesList)
for index, referenceName := range referenceNamesList{
referenceLink, exists := referencesMap[referenceName]
if (exists == false){
setErrorEncounteredPage(window, errors.New("referencesMap missing referenceName"), previousPage)
return
}
indexString := helpers.ConvertIntToString(index+1)
indexLabel := getBoldLabel(indexString + ".")
referenceNameTrimmed, _, err := helpers.TrimAndFlattenString(referenceName, 35)
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
referenceNameLabel := getItalicLabel(referenceNameTrimmed)
referenceViewNameButton := widget.NewButtonWithIcon("View Name", theme.VisibilityIcon(), func(){
setViewTextPage(window, "Viewing Reference Name", referenceName, false, currentPage)
})
referenceLinkButton := widget.NewButtonWithIcon("View Link", theme.VisibilityIcon(), func(){
setViewLinkPage(window, "Viewing Reference Link", referenceLink, currentPage)
})
referenceRow := container.NewHBox(layout.NewSpacer(), indexLabel, referenceNameLabel, referenceViewNameButton, referenceLinkButton, layout.NewSpacer())
referencesContainer.Add(referenceRow)
referencesContainer.Add(widget.NewSeparator())
}
page := container.NewVBox(title, backButton, widget.NewSeparator(), referencesContainer)
setPageContent(page, window)
}
func setViewTraitDetailsPage(window fyne.Window, traitName string, previousPage func()){
currentPage := func(){setViewTraitDetailsPage(window, traitName, previousPage)}
title := getPageTitleCentered("Trait Details - " + traitName)
backButton := getBackButtonCentered(previousPage)
traitObject, err := traits.GetTraitObject(traitName)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
traitDescription := traitObject.TraitDescription
traitReferencesMap := traitObject.ReferencesMap
traitNameLabel := widget.NewLabel("Trait Name:")
traitNameText := getBoldLabel(traitName)
traitNameRow := container.NewHBox(layout.NewSpacer(), traitNameLabel, traitNameText, layout.NewSpacer())
traitDescriptionTrimmed, _, err := helpers.TrimAndFlattenString(traitDescription, 10)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
traitDescriptionLabel := widget.NewLabel("Description:")
traitDescriptionText := getBoldLabel(traitDescriptionTrimmed)
viewTraitDescriptionButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
setViewTextPage(window, "Trait Description", traitDescription, false, currentPage)
})
traitDescriptionRow := container.NewHBox(layout.NewSpacer(), traitDescriptionLabel, traitDescriptionText, viewTraitDescriptionButton, layout.NewSpacer())
viewReferencesButton := getWidgetCentered(widget.NewButtonWithIcon("View References", theme.ListIcon(), func(){
setViewGeneticAnalysisReferencesPage(window, "Trait", traitReferencesMap, currentPage)
}))
page := container.NewVBox(title, backButton, widget.NewSeparator(), traitNameRow, widget.NewSeparator(), traitDescriptionRow, widget.NewSeparator(), viewReferencesButton)
setPageContent(page, window)
}
func setViewDiscreteTraitRuleDetailsPage(window fyne.Window, traitName string, ruleIdentifier string, previousPage func()){
currentPage := func(){setViewDiscreteTraitRuleDetailsPage(window, traitName, ruleIdentifier, previousPage)}
title := getPageTitleCentered("Viewing Rule Details")
backButton := getBackButtonCentered(previousPage)
traitNameLabel := widget.NewLabel("Trait Name:")
traitNameText := getBoldLabel(traitName)
traitNameRow := container.NewHBox(layout.NewSpacer(), traitNameLabel, traitNameText, layout.NewSpacer())
ruleIdentifierLabel := widget.NewLabel("Rule Identifier:")
ruleIdentifierText := getBoldLabel(ruleIdentifier)
ruleIdentifierRow := container.NewHBox(layout.NewSpacer(), ruleIdentifierLabel, ruleIdentifierText, layout.NewSpacer())
traitRuleObject, err := traits.GetTraitRuleObject(traitName, ruleIdentifier)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
ruleOutcomePointsMap := traitRuleObject.OutcomePointsMap
ruleReferencesMap := traitRuleObject.ReferencesMap
viewReferencesButton := getWidgetCentered(widget.NewButtonWithIcon("View References", theme.ListIcon(), func(){
setViewGeneticAnalysisReferencesPage(window, "Rule", ruleReferencesMap, currentPage)
}))
ruleEffectsLabel := getBoldLabelCentered("Rule Effects:")
getRuleEffectsGrid := func()(*fyne.Container, error){
outcomeNameLabel := getItalicLabelCentered("Outcome Name")
outcomeEffectLabel := getItalicLabelCentered("Outcome Effect")
outcomeNameColumn := container.NewVBox(outcomeNameLabel, widget.NewSeparator())
outcomeEffectColumn := container.NewVBox(outcomeEffectLabel, widget.NewSeparator())
for outcomeName, outcomePointsEffect := range ruleOutcomePointsMap{
outcomeNameLabel := getBoldLabelCentered(outcomeName)
getOutcomeEffect := func()string{
outcomePointsEffectString := helpers.ConvertIntToString(outcomePointsEffect)
if (outcomePointsEffect < 0){
return outcomePointsEffectString
}
outcomeEffect := "+" + outcomePointsEffectString
return outcomeEffect
}
outcomeEffect := getOutcomeEffect()
outcomeEffectLabel := getBoldLabelCentered(outcomeEffect)
outcomeNameColumn.Add(outcomeNameLabel)
outcomeEffectColumn.Add(outcomeEffectLabel)
outcomeNameColumn.Add(widget.NewSeparator())
outcomeEffectColumn.Add(widget.NewSeparator())
}
outcomeEffectHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
setDiscreteTraitRuleOutcomeEffectsExplainerPage(window, currentPage)
})
outcomeEffectColumn.Add(outcomeEffectHelpButton)
ruleEffectsGrid := container.NewHBox(layout.NewSpacer(), outcomeNameColumn, outcomeEffectColumn, layout.NewSpacer())
return ruleEffectsGrid, nil
}
ruleEffectsGrid, err := getRuleEffectsGrid()
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
page := container.NewVBox(title, backButton, widget.NewSeparator(), traitNameRow, widget.NewSeparator(), ruleIdentifierRow, widget.NewSeparator(), viewReferencesButton, widget.NewSeparator(), ruleEffectsLabel, ruleEffectsGrid)
setPageContent(page, window)
}