Compare commits
4 commits
497f596b3b
...
edecfa4b16
Author | SHA1 | Date | |
---|---|---|---|
|
edecfa4b16 | ||
|
8b0c41af45 | ||
|
649bf318c2 | ||
|
ee976f49b3 |
24 changed files with 2443 additions and 1810 deletions
|
@ -6,6 +6,10 @@ Small and insignificant changes may not be included in this log.
|
|||
|
||||
## Unversioned Changes
|
||||
|
||||
* Added "User Has Disease" information to the View Profile - Monogenic Diseases page. - *Simon Sarasova*
|
||||
* Created the calculatedAttributes_test package. - *Simon Sarasova*
|
||||
* Improved the creation process of genetic analyses in various ways. A sample of offspring polygenic disease risk scores are now created and viewable by users. - *Simon Sarasova*
|
||||
* Improved the genetic analysis creation process in various ways. Recombination breakpoints are more accurately predicted now. - *Simon Sarasova*
|
||||
* Improved the identity hash generation tool. The fastest quantity of goroutines is now identified and used. - *Simon Sarasova*
|
||||
* Improved the creation procedures, encoding format, and graphical presentation of genetic analyses. Map lists have been replaced by custom objects. - *Simon Sarasova*
|
||||
* Upgraded Circl to version 1.3.8. - *Simon Sarasova*
|
||||
|
|
|
@ -9,4 +9,4 @@ Many other people have written code for modules which are imported by Seekia. Th
|
|||
|
||||
Name | Date Of First Commit | Number Of Commits
|
||||
--- | --- | ---
|
||||
Simon Sarasova | June 13, 2023 | 249
|
||||
Simon Sarasova | June 13, 2023 | 253
|
|
@ -18,6 +18,7 @@ import "seekia/internal/helpers"
|
|||
import "seekia/internal/network/appNetworkType/getAppNetworkType"
|
||||
import "seekia/internal/profiles/attributeDisplay"
|
||||
import "seekia/internal/profiles/userStatistics"
|
||||
import "seekia/internal/statisticsDatum"
|
||||
|
||||
import "errors"
|
||||
import "image"
|
||||
|
@ -146,13 +147,13 @@ func setViewUserAttributeStatisticsPage_BarChart(
|
|||
showYAxisPercentage bool,
|
||||
statisticsReady bool,
|
||||
anyUsersExist bool,
|
||||
statisticsItemsList []userStatistics.StatisticsItem,
|
||||
statisticsDatumsList []statisticsDatum.StatisticsDatum,
|
||||
groupingPerformed bool,
|
||||
groupedStatisticsItemsList []userStatistics.StatisticsItem,
|
||||
groupedStatisticsDatumsList []statisticsDatum.StatisticsDatum,
|
||||
chartImage image.Image,
|
||||
previousPage func()){
|
||||
|
||||
currentPage := func(){setViewUserAttributeStatisticsPage_BarChart(window, identityType, xAxisAttributeName, yAxisAttribute, yAxisUnits, showYAxisPercentage, statisticsReady, anyUsersExist, statisticsItemsList, groupingPerformed, groupedStatisticsItemsList, chartImage, previousPage)}
|
||||
currentPage := func(){setViewUserAttributeStatisticsPage_BarChart(window, identityType, xAxisAttributeName, yAxisAttribute, yAxisUnits, showYAxisPercentage, statisticsReady, anyUsersExist, statisticsDatumsList, groupingPerformed, groupedStatisticsDatumsList, chartImage, previousPage)}
|
||||
|
||||
pageIdentifier, err := helpers.GetNewRandomHexString(16)
|
||||
if (err != nil) {
|
||||
|
@ -264,7 +265,7 @@ func setViewUserAttributeStatisticsPage_BarChart(
|
|||
}
|
||||
|
||||
viewDataButton := widget.NewButtonWithIcon("View Data", theme.ListIcon(), func(){
|
||||
setViewUserStatisticsDataPage(window, xAxisAttributeTitle, yAxisAttribute, showYAxisPercentage, statisticsItemsList, groupingPerformed, groupedStatisticsItemsList, true, xAxisUnits, yAxisUnits, currentPage)
|
||||
setViewUserStatisticsDataPage(window, xAxisAttributeTitle, yAxisAttribute, showYAxisPercentage, statisticsDatumsList, groupingPerformed, groupedStatisticsDatumsList, true, xAxisUnits, yAxisUnits, currentPage)
|
||||
})
|
||||
|
||||
viewFullscreenButton := widget.NewButtonWithIcon("View Fullscreen", theme.ZoomInIcon(), func(){
|
||||
|
@ -336,7 +337,7 @@ func setViewUserAttributeStatisticsPage_BarChart(
|
|||
|
||||
go updateLoadingBindingFunction()
|
||||
|
||||
totalAnalyzedUsers, statisticsItemsList, groupingPerformed, groupedStatisticsItemsList, formatYAxisValuesFunction, err := userStatistics.GetUserStatisticsItemsLists_BarChart(identityType, appNetworkType, xAxisAttributeName, xAxisIsNumerical, formatXAxisValuesFunction, unknownXAxisValuesTextTranslated, yAxisAttribute)
|
||||
totalAnalyzedUsers, statisticsDatumsList, groupingPerformed, groupedStatisticsDatumsList, formatYAxisValuesFunction, err := userStatistics.GetUserStatisticsDatumsLists_BarChart(identityType, appNetworkType, xAxisAttributeName, xAxisIsNumerical, formatXAxisValuesFunction, unknownXAxisValuesTextTranslated, yAxisAttribute)
|
||||
if (err != nil) {
|
||||
|
||||
functionCompleteBoolMutex.Lock()
|
||||
|
@ -350,7 +351,7 @@ func setViewUserAttributeStatisticsPage_BarChart(
|
|||
return
|
||||
}
|
||||
|
||||
if (len(statisticsItemsList) == 0){
|
||||
if (len(statisticsDatumsList) == 0){
|
||||
|
||||
functionCompleteBoolMutex.Lock()
|
||||
functionCompleteBool = true
|
||||
|
@ -363,14 +364,14 @@ func setViewUserAttributeStatisticsPage_BarChart(
|
|||
return
|
||||
}
|
||||
|
||||
getChartStatisticsItemsList := func()[]userStatistics.StatisticsItem{
|
||||
getChartStatisticsDatumsList := func()[]statisticsDatum.StatisticsDatum{
|
||||
if (groupingPerformed == false){
|
||||
return statisticsItemsList
|
||||
return statisticsDatumsList
|
||||
}
|
||||
return groupedStatisticsItemsList
|
||||
return groupedStatisticsDatumsList
|
||||
}
|
||||
|
||||
chartStatisticsItemsList := getChartStatisticsItemsList()
|
||||
chartStatisticsDatumsList := getChartStatisticsDatumsList()
|
||||
|
||||
getChartTitle := func()string{
|
||||
|
||||
|
@ -401,7 +402,7 @@ func setViewUserAttributeStatisticsPage_BarChart(
|
|||
|
||||
chartTitle := getChartTitle()
|
||||
|
||||
newChartImage, err := createCharts.CreateBarChart(chartTitle, chartStatisticsItemsList, formatYAxisValuesFunction, true, yAxisUnits)
|
||||
newChartImage, err := createCharts.CreateBarChart(chartTitle, chartStatisticsDatumsList, formatYAxisValuesFunction, true, yAxisUnits)
|
||||
if (err != nil) {
|
||||
|
||||
functionCompleteBoolMutex.Lock()
|
||||
|
@ -421,7 +422,7 @@ func setViewUserAttributeStatisticsPage_BarChart(
|
|||
|
||||
pageHasChanged := checkIfPageHasChangedFunction()
|
||||
if (pageHasChanged == false){
|
||||
setViewUserAttributeStatisticsPage_BarChart(window, identityType, xAxisAttributeName, yAxisAttribute, yAxisUnits, showYAxisPercentage, true, true, statisticsItemsList, groupingPerformed, groupedStatisticsItemsList, newChartImage, previousPage)
|
||||
setViewUserAttributeStatisticsPage_BarChart(window, identityType, xAxisAttributeName, yAxisAttribute, yAxisUnits, showYAxisPercentage, true, true, statisticsDatumsList, groupingPerformed, groupedStatisticsDatumsList, newChartImage, previousPage)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,13 +442,13 @@ func setViewUserAttributeStatisticsPage_DonutChart(
|
|||
attributeName string,
|
||||
statisticsReady bool,
|
||||
anyUsersExist bool,
|
||||
statisticsItemsList []userStatistics.StatisticsItem,
|
||||
statisticsDatumsList []statisticsDatum.StatisticsDatum,
|
||||
groupingPerformed bool,
|
||||
groupedStatisticsItemsList []userStatistics.StatisticsItem,
|
||||
groupedStatisticsDatumsList []statisticsDatum.StatisticsDatum,
|
||||
chartImage image.Image,
|
||||
previousPage func()){
|
||||
|
||||
currentPage := func(){setViewUserAttributeStatisticsPage_DonutChart(window, identityType, attributeName, statisticsReady, anyUsersExist, statisticsItemsList, groupingPerformed, groupedStatisticsItemsList, chartImage, previousPage)}
|
||||
currentPage := func(){setViewUserAttributeStatisticsPage_DonutChart(window, identityType, attributeName, statisticsReady, anyUsersExist, statisticsDatumsList, groupingPerformed, groupedStatisticsDatumsList, chartImage, previousPage)}
|
||||
|
||||
pageIdentifier, err := helpers.GetNewRandomHexString(16)
|
||||
if (err != nil) {
|
||||
|
@ -545,7 +546,7 @@ func setViewUserAttributeStatisticsPage_DonutChart(
|
|||
|
||||
viewDataButton := widget.NewButtonWithIcon("View Data", theme.ListIcon(), func(){
|
||||
|
||||
setViewUserStatisticsDataPage(window, attributeTitle, "Number Of Users", true, statisticsItemsList, groupingPerformed, groupedStatisticsItemsList, true, attributeUnits, "Users", currentPage)
|
||||
setViewUserStatisticsDataPage(window, attributeTitle, "Number Of Users", true, statisticsDatumsList, groupingPerformed, groupedStatisticsDatumsList, true, attributeUnits, "Users", currentPage)
|
||||
})
|
||||
|
||||
viewFullscreenButton := widget.NewButtonWithIcon("View Fullscreen", theme.ZoomInIcon(), func(){
|
||||
|
@ -616,7 +617,7 @@ func setViewUserAttributeStatisticsPage_DonutChart(
|
|||
|
||||
go updateLoadingBindingFunction()
|
||||
|
||||
totalAnalyzedUsers, statisticsItemsList, groupingPerformed, groupedStatisticsItemsList, err := userStatistics.GetUserStatisticsItemsLists_DonutChart(identityType, appNetworkType, attributeName, attributeIsNumerical, formatAttributeValuesFunction, unknownValuesTextTranslated)
|
||||
totalAnalyzedUsers, statisticsDatumsList, groupingPerformed, groupedStatisticsDatumsList, err := userStatistics.GetUserStatisticsDatumsLists_DonutChart(identityType, appNetworkType, attributeName, attributeIsNumerical, formatAttributeValuesFunction, unknownValuesTextTranslated)
|
||||
if (err != nil) {
|
||||
|
||||
functionCompleteBoolMutex.Lock()
|
||||
|
@ -630,7 +631,7 @@ func setViewUserAttributeStatisticsPage_DonutChart(
|
|||
return
|
||||
}
|
||||
|
||||
if (len(statisticsItemsList) == 0){
|
||||
if (len(statisticsDatumsList) == 0){
|
||||
|
||||
functionCompleteBoolMutex.Lock()
|
||||
functionCompleteBool = true
|
||||
|
@ -643,14 +644,14 @@ func setViewUserAttributeStatisticsPage_DonutChart(
|
|||
return
|
||||
}
|
||||
|
||||
getChartStatisticsItemsList := func()[]userStatistics.StatisticsItem{
|
||||
getChartStatisticsDatumsList := func()[]statisticsDatum.StatisticsDatum{
|
||||
if (groupingPerformed == false){
|
||||
return statisticsItemsList
|
||||
return statisticsDatumsList
|
||||
}
|
||||
return groupedStatisticsItemsList
|
||||
return groupedStatisticsDatumsList
|
||||
}
|
||||
|
||||
chartStatisticsItemsList := getChartStatisticsItemsList()
|
||||
chartStatisticsDatumsList := getChartStatisticsDatumsList()
|
||||
|
||||
getChartTitle := func()string{
|
||||
|
||||
|
@ -672,7 +673,7 @@ func setViewUserAttributeStatisticsPage_DonutChart(
|
|||
|
||||
chartTitle := getChartTitle()
|
||||
|
||||
newChartImage, err := createCharts.CreateDonutChart(chartTitle, chartStatisticsItemsList)
|
||||
newChartImage, err := createCharts.CreateDonutChart(chartTitle, chartStatisticsDatumsList)
|
||||
if (err != nil){
|
||||
|
||||
functionCompleteBoolMutex.Lock()
|
||||
|
@ -692,7 +693,7 @@ func setViewUserAttributeStatisticsPage_DonutChart(
|
|||
|
||||
pageHasChanged := checkIfPageHasChangedFunction()
|
||||
if (pageHasChanged == false){
|
||||
setViewUserAttributeStatisticsPage_DonutChart(window, identityType, attributeName, true, true, statisticsItemsList, groupingPerformed, groupedStatisticsItemsList, newChartImage, previousPage)
|
||||
setViewUserAttributeStatisticsPage_DonutChart(window, identityType, attributeName, true, true, statisticsDatumsList, groupingPerformed, groupedStatisticsDatumsList, newChartImage, previousPage)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -934,9 +935,9 @@ func setViewUserStatisticsDataPage(
|
|||
attributeTitle string,
|
||||
rightColumnName string,
|
||||
showPercentageColumn bool,
|
||||
statisticsItemsList []userStatistics.StatisticsItem,
|
||||
statisticsDatumsList []statisticsDatum.StatisticsDatum,
|
||||
groupingPerformed bool,
|
||||
groupedStatisticsItemsList []userStatistics.StatisticsItem,
|
||||
groupedStatisticsDatumsList []statisticsDatum.StatisticsDatum,
|
||||
showGroupedStatistics bool,
|
||||
attributeColumnUnits string,
|
||||
rightColumnUnits string,
|
||||
|
@ -954,13 +955,13 @@ func setViewUserStatisticsDataPage(
|
|||
|
||||
if (showGroupedStatistics == false){
|
||||
showDataGroupedButton := getWidgetCentered(widget.NewButton("Show Data Grouped", func(){
|
||||
setViewUserStatisticsDataPage(window, attributeTitle, rightColumnName, showPercentageColumn, statisticsItemsList, true, groupedStatisticsItemsList, true, attributeColumnUnits, rightColumnUnits, previousPage)
|
||||
setViewUserStatisticsDataPage(window, attributeTitle, rightColumnName, showPercentageColumn, statisticsDatumsList, true, groupedStatisticsDatumsList, true, attributeColumnUnits, rightColumnUnits, previousPage)
|
||||
}))
|
||||
|
||||
header.Add(showDataGroupedButton)
|
||||
} else {
|
||||
showDataRawButton := getWidgetCentered(widget.NewButton("Show Data Raw", func(){
|
||||
setViewUserStatisticsDataPage(window, attributeTitle, rightColumnName, showPercentageColumn, statisticsItemsList, true, groupedStatisticsItemsList, false, attributeColumnUnits, rightColumnUnits, previousPage)
|
||||
setViewUserStatisticsDataPage(window, attributeTitle, rightColumnName, showPercentageColumn, statisticsDatumsList, true, groupedStatisticsDatumsList, false, attributeColumnUnits, rightColumnUnits, previousPage)
|
||||
}))
|
||||
|
||||
header.Add(showDataRawButton)
|
||||
|
@ -968,14 +969,14 @@ func setViewUserStatisticsDataPage(
|
|||
header.Add(widget.NewSeparator())
|
||||
}
|
||||
|
||||
getStatisticsItemsListToShow := func()[]userStatistics.StatisticsItem{
|
||||
getStatisticsDatumsListToShow := func()[]statisticsDatum.StatisticsDatum{
|
||||
if (groupingPerformed == true && showGroupedStatistics == true){
|
||||
return groupedStatisticsItemsList
|
||||
return groupedStatisticsDatumsList
|
||||
}
|
||||
return statisticsItemsList
|
||||
return statisticsDatumsList
|
||||
}
|
||||
|
||||
statisticsItemsToShowList := getStatisticsItemsListToShow()
|
||||
statisticsDatumsToShowList := getStatisticsDatumsListToShow()
|
||||
|
||||
getStatisticsDataGrid := func()(*fyne.Container, error){
|
||||
|
||||
|
@ -983,38 +984,38 @@ func setViewUserStatisticsDataPage(
|
|||
|
||||
if (showPercentageColumn == true){
|
||||
|
||||
for _, item := range statisticsItemsToShowList{
|
||||
for _, datum := range statisticsDatumsToShowList{
|
||||
|
||||
itemValue := item.Value
|
||||
datumValue := datum.Value
|
||||
|
||||
allValuesSummed += itemValue
|
||||
allValuesSummed += datumValue
|
||||
}
|
||||
}
|
||||
|
||||
attributeColumnValuesList := make([]string, 0, len(statisticsItemsToShowList))
|
||||
rightColumnValuesList := make([]string, 0, len(statisticsItemsToShowList))
|
||||
percentageColumnValuesList := make([]string, 0, len(statisticsItemsToShowList))
|
||||
attributeColumnValuesList := make([]string, 0, len(statisticsDatumsToShowList))
|
||||
rightColumnValuesList := make([]string, 0, len(statisticsDatumsToShowList))
|
||||
percentageColumnValuesList := make([]string, 0, len(statisticsDatumsToShowList))
|
||||
|
||||
for _, item := range statisticsItemsToShowList{
|
||||
for _, datum := range statisticsDatumsToShowList{
|
||||
|
||||
// Each item is represents a row in the data grid.
|
||||
// Each datum is represents a row in the data grid.
|
||||
|
||||
itemLabelFormatted := item.LabelFormatted
|
||||
datumLabelFormatted := datum.LabelFormatted
|
||||
|
||||
itemValueFormatted := item.ValueFormatted
|
||||
datumValueFormatted := datum.ValueFormatted
|
||||
|
||||
attributeColumnValuesList = append(attributeColumnValuesList, itemLabelFormatted)
|
||||
rightColumnValuesList = append(rightColumnValuesList, itemValueFormatted)
|
||||
attributeColumnValuesList = append(attributeColumnValuesList, datumLabelFormatted)
|
||||
rightColumnValuesList = append(rightColumnValuesList, datumValueFormatted)
|
||||
|
||||
if (showPercentageColumn == true){
|
||||
|
||||
itemValue := item.Value
|
||||
datumValue := datum.Value
|
||||
|
||||
getValuePercentage := func()float64{
|
||||
if (allValuesSummed == 0){
|
||||
return 0
|
||||
}
|
||||
valuePercentage := (itemValue/allValuesSummed)*100
|
||||
valuePercentage := (datumValue/allValuesSummed)*100
|
||||
return valuePercentage
|
||||
}
|
||||
|
||||
|
|
|
@ -8,20 +8,24 @@ import "fyne.io/fyne/v2/container"
|
|||
import "fyne.io/fyne/v2/layout"
|
||||
import "fyne.io/fyne/v2/theme"
|
||||
import "fyne.io/fyne/v2/widget"
|
||||
import "fyne.io/fyne/v2/canvas"
|
||||
|
||||
import "seekia/resources/geneticReferences/monogenicDiseases"
|
||||
import "seekia/resources/geneticReferences/polygenicDiseases"
|
||||
import "seekia/resources/geneticReferences/traits"
|
||||
|
||||
import "seekia/internal/appMemory"
|
||||
import "seekia/internal/createCharts"
|
||||
import "seekia/internal/encoding"
|
||||
import "seekia/internal/genetics/geneticAnalysis"
|
||||
import "seekia/internal/genetics/myGenomes"
|
||||
import "seekia/internal/genetics/myPeople"
|
||||
import "seekia/internal/genetics/readGeneticAnalysis"
|
||||
import "seekia/internal/helpers"
|
||||
import "seekia/internal/statisticsDatum"
|
||||
|
||||
import "slices"
|
||||
import "image"
|
||||
import "errors"
|
||||
|
||||
|
||||
|
@ -1006,7 +1010,7 @@ func setViewCoupleGeneticAnalysisPolygenicDiseasesPage(window fyne.Window, perso
|
|||
|
||||
mainGenomePairIdentifier := helpers.JoinTwo16ByteArrays(pair1Person1GenomeIdentifier, pair1Person2GenomeIdentifier)
|
||||
|
||||
offspringRiskScoreKnown, _, offspringRiskScoreFormatted, _, conflictExists, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, mainGenomePairIdentifier)
|
||||
offspringRiskScoreKnown, _, offspringRiskScoreFormatted, _, _, conflictExists, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, mainGenomePairIdentifier)
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
getRiskScoreLabelText := func()string{
|
||||
|
@ -1116,25 +1120,27 @@ func setViewCoupleGeneticAnalysisPolygenicDiseaseDetailsPage(window fyne.Window,
|
|||
})
|
||||
diseaseNameRow := container.NewHBox(layout.NewSpacer(), diseaseNameLabel, diseaseNameText, diseaseNameInfoButton, layout.NewSpacer())
|
||||
|
||||
emptyLabelA := widget.NewLabel("")
|
||||
emptyLabelB := widget.NewLabel("")
|
||||
emptyLabel1 := widget.NewLabel("")
|
||||
emptyLabel2 := widget.NewLabel("")
|
||||
|
||||
offspringRiskScoreLabel := getItalicLabelCentered("Offspring Risk Score")
|
||||
|
||||
emptyLabelC := widget.NewLabel("")
|
||||
emptyLabelD := widget.NewLabel("")
|
||||
emptyLabel3 := widget.NewLabel("")
|
||||
emptyLabel4 := widget.NewLabel("")
|
||||
emptyLabel5 := widget.NewLabel("")
|
||||
|
||||
viewGenomePairButtonsColumn := container.NewVBox(emptyLabelA, widget.NewSeparator())
|
||||
pairNameColumn := container.NewVBox(emptyLabelB, widget.NewSeparator())
|
||||
viewGenomePairButtonsColumn := container.NewVBox(emptyLabel1, widget.NewSeparator())
|
||||
pairNameColumn := container.NewVBox(emptyLabel2, widget.NewSeparator())
|
||||
offspringRiskScoreColumn := container.NewVBox(offspringRiskScoreLabel, widget.NewSeparator())
|
||||
viewLifetimeRiskButtonsColumn := container.NewVBox(emptyLabelC, widget.NewSeparator())
|
||||
viewOffspringLociButtonsColumn := container.NewVBox(emptyLabelD, widget.NewSeparator())
|
||||
viewSampleOffspringsChartButtonsColumn := container.NewVBox(emptyLabel3, widget.NewSeparator())
|
||||
viewLifetimeRiskButtonsColumn := container.NewVBox(emptyLabel4, widget.NewSeparator())
|
||||
viewOffspringLociButtonsColumn := container.NewVBox(emptyLabel5, widget.NewSeparator())
|
||||
|
||||
addGenomePairRow := func(genomePairName string, person1GenomeIdentifier [16]byte, person2GenomeIdentifier [16]byte)error{
|
||||
|
||||
genomePairIdentifier := helpers.JoinTwo16ByteArrays(person1GenomeIdentifier, person2GenomeIdentifier)
|
||||
|
||||
offspringRiskScoreKnown, _, offspringRiskScoreFormatted, _, _, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, genomePairIdentifier)
|
||||
offspringRiskScoreKnown, _, offspringRiskScoreFormatted, sampleOffspringRiskScoresList, numberOfLociTested, _, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, genomePairIdentifier)
|
||||
if (err != nil) { return err }
|
||||
|
||||
getRiskScoreLabelText := func()string{
|
||||
|
@ -1158,6 +1164,10 @@ func setViewCoupleGeneticAnalysisPolygenicDiseaseDetailsPage(window fyne.Window,
|
|||
setViewCoupleGeneticAnalysisPolygenicDiseaseGenomePairDetailsPage(window, person1Name, person2Name, person1AnalysisObject, person2AnalysisObject, coupleAnalysisObject, diseaseName, genomePairIdentifier, genomePairName, currentPage)
|
||||
})
|
||||
|
||||
viewSampleOffspringsChartButton := widget.NewButtonWithIcon("", theme.InfoIcon(), func(){
|
||||
setViewPolygenicDiseaseSampleOffspringRiskScoresChart(window, diseaseName, sampleOffspringRiskScoresList, numberOfLociTested, currentPage)
|
||||
})
|
||||
|
||||
viewOffspringLifetimeRiskButton := widget.NewButtonWithIcon("", theme.HistoryIcon(), func(){
|
||||
|
||||
diseaseObject, err := polygenicDiseases.GetPolygenicDiseaseObject(diseaseName)
|
||||
|
@ -1190,12 +1200,15 @@ func setViewCoupleGeneticAnalysisPolygenicDiseaseDetailsPage(window fyne.Window,
|
|||
viewGenomePairButtonsColumn.Add(viewGenomePairButton)
|
||||
pairNameColumn.Add(genomePairNameLabel)
|
||||
offspringRiskScoreColumn.Add(offspringRiskScoreLabel)
|
||||
viewSampleOffspringsChartButtonsColumn.Add(viewSampleOffspringsChartButton)
|
||||
viewLifetimeRiskButtonsColumn.Add(viewOffspringLifetimeRiskButton)
|
||||
viewOffspringLociButtonsColumn.Add(viewOffspringLociButton)
|
||||
|
||||
viewGenomePairButtonsColumn.Add(widget.NewSeparator())
|
||||
pairNameColumn.Add(widget.NewSeparator())
|
||||
offspringRiskScoreColumn.Add(widget.NewSeparator())
|
||||
viewSampleOffspringsChartButtonsColumn.Add(widget.NewSeparator())
|
||||
viewLifetimeRiskButtonsColumn.Add(widget.NewSeparator())
|
||||
viewOffspringLociButtonsColumn.Add(widget.NewSeparator())
|
||||
|
||||
return nil
|
||||
|
@ -1221,7 +1234,7 @@ func setViewCoupleGeneticAnalysisPolygenicDiseaseDetailsPage(window fyne.Window,
|
|||
|
||||
offspringRiskScoreColumn.Add(offspringRiskScoreHelpButton)
|
||||
|
||||
genomesContainer := container.NewHBox(layout.NewSpacer(), viewGenomePairButtonsColumn, pairNameColumn, offspringRiskScoreColumn, viewOffspringLociButtonsColumn, layout.NewSpacer())
|
||||
genomesContainer := container.NewHBox(layout.NewSpacer(), viewGenomePairButtonsColumn, pairNameColumn, offspringRiskScoreColumn, viewSampleOffspringsChartButtonsColumn, viewLifetimeRiskButtonsColumn, viewOffspringLociButtonsColumn, layout.NewSpacer())
|
||||
|
||||
page := container.NewVBox(title, backButton, widget.NewSeparator(), descriptionSection, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), genomesContainer)
|
||||
|
||||
|
@ -1314,7 +1327,7 @@ func setViewCoupleGeneticAnalysisPolygenicDiseaseGenomePairDetailsPage(window fy
|
|||
|
||||
genomeNameLabel := getBoldLabelCentered(genomeName)
|
||||
|
||||
personRiskScoreKnown, _, personRiskScoreFormatted, numberOfLociTested, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(personAnalysisObject, diseaseName, personAnalysisGenomeIdentifier)
|
||||
personRiskScoreKnown, _, personRiskScoreFormatted, _, numberOfLociTested, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(personAnalysisObject, diseaseName, personAnalysisGenomeIdentifier)
|
||||
if (err != nil) { return err }
|
||||
|
||||
getPersonRiskScoreLabelText := func()string{
|
||||
|
@ -1408,7 +1421,7 @@ func setViewCouplePolygenicDiseaseLociPage(window fyne.Window, person1Name strin
|
|||
|
||||
genomePairRow := container.NewHBox(layout.NewSpacer(), genomePairLabel, genomePairNameLabel, viewGenomePairInfoButton, layout.NewSpacer())
|
||||
|
||||
_, _, _, numberOfLociTested, _, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, genomePairIdentifier)
|
||||
_, _, _, _, numberOfLociTested, _, err := readGeneticAnalysis.GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, genomePairIdentifier)
|
||||
if (err != nil){
|
||||
setErrorEncounteredPage(window, err, previousPage)
|
||||
return
|
||||
|
@ -1719,6 +1732,133 @@ func setViewCoupleGeneticAnalysisPolygenicDiseaseLocusDetailsPage(window fyne.Wi
|
|||
setPageContent(page, window)
|
||||
}
|
||||
|
||||
// This is a page that shows the user 100 sample offspring polygenic disease risk scores on a bar chart
|
||||
// This helps users to visualize the standard deviation of their offspring's disease risk with this user
|
||||
func setViewPolygenicDiseaseSampleOffspringRiskScoresChart(window fyne.Window, diseaseName string, sampleOffspringRiskScoresList []int, numberOfLociTested int, previousPage func()){
|
||||
|
||||
currentPage := func(){setViewPolygenicDiseaseSampleOffspringRiskScoresChart(window, diseaseName, sampleOffspringRiskScoresList, numberOfLociTested, previousPage)}
|
||||
|
||||
title := getPageTitleCentered("Viewing Sample Offspring Risk Scores Chart")
|
||||
|
||||
backButton := getBackButtonCentered(previousPage)
|
||||
|
||||
description := widget.NewLabel("Below is a chart of 100 sample offspring risk scores for this disease.")
|
||||
descriptionHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
||||
//TODO
|
||||
showUnderConstructionDialog(window)
|
||||
})
|
||||
descriptionRow := container.NewHBox(layout.NewSpacer(), description, descriptionHelpButton, layout.NewSpacer())
|
||||
|
||||
diseaseNameTitle := widget.NewLabel("Disease Name:")
|
||||
diseaseNameLabel := getBoldLabel(diseaseName)
|
||||
diseaseNameRow := container.NewHBox(layout.NewSpacer(), diseaseNameTitle, diseaseNameLabel, layout.NewSpacer())
|
||||
|
||||
if (len(sampleOffspringRiskScoresList) == 0){
|
||||
description2 := getBoldLabelCentered("There is no offspring information available for this disease.")
|
||||
description3 := getBoldLabelCentered("This is because there were no disease loci for which both prospective parents had information.")
|
||||
|
||||
page := container.NewVBox(title, backButton, widget.NewSeparator(), descriptionRow, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), description2, description3)
|
||||
|
||||
setPageContent(page, window)
|
||||
return
|
||||
}
|
||||
|
||||
diseaseLociMap, err := polygenicDiseases.GetPolygenicDiseaseLociMap(diseaseName)
|
||||
if (err != nil){
|
||||
setErrorEncounteredPage(window, err, previousPage)
|
||||
return
|
||||
}
|
||||
|
||||
totalNumberOfLoci := len(diseaseLociMap)
|
||||
totalNumberOfLociString := helpers.ConvertIntToString(totalNumberOfLoci)
|
||||
|
||||
numberOfLociTestedTitle := widget.NewLabel("Number Of Loci Tested:")
|
||||
numberOfLociTestedString := helpers.ConvertIntToString(numberOfLociTested)
|
||||
numberOfLociTestedLabel := getBoldLabel(numberOfLociTestedString + "/" + totalNumberOfLociString)
|
||||
|
||||
lociTestedHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
||||
setOffspringPolygenicDiseaseNumberOfLociTestedExplainerPage(window, currentPage)
|
||||
})
|
||||
|
||||
numberOfLociTestedRow := container.NewHBox(layout.NewSpacer(), numberOfLociTestedTitle, numberOfLociTestedLabel, lociTestedHelpButton, layout.NewSpacer())
|
||||
|
||||
getOffspringSampleRiskScoresChartImage := func()(image.Image, error){
|
||||
|
||||
// Map Structure: Risk Score -> Number of offspring with that risk score
|
||||
offspringRiskScoreCountsMap := make(map[int]int)
|
||||
|
||||
for _, offspringRiskScore := range sampleOffspringRiskScoresList{
|
||||
offspringRiskScoreCountsMap[offspringRiskScore] += 1
|
||||
}
|
||||
|
||||
//TODO: Move StatisticsDatum to its own package, because we are using it for non-user purposes, and will continue to do so
|
||||
offspringStatisticsDatumsList := make([]statisticsDatum.StatisticsDatum, 0)
|
||||
|
||||
for riskScore:=0; riskScore <= 10; riskScore += 1{
|
||||
|
||||
getOffspringCount := func()int{
|
||||
|
||||
offspringCount, exists := offspringRiskScoreCountsMap[riskScore]
|
||||
if (exists == false){
|
||||
return 0
|
||||
}
|
||||
return offspringCount
|
||||
}
|
||||
|
||||
offspringCount := getOffspringCount()
|
||||
|
||||
riskScoreString := helpers.ConvertIntToString(riskScore)
|
||||
offspringCountString := helpers.ConvertIntToString(offspringCount)
|
||||
|
||||
newStatisticsDatum := statisticsDatum.StatisticsDatum{
|
||||
|
||||
Label: riskScoreString + "/10",
|
||||
LabelFormatted: riskScoreString + "/10",
|
||||
Value: float64(offspringCount),
|
||||
ValueFormatted: offspringCountString,
|
||||
}
|
||||
|
||||
offspringStatisticsDatumsList = append(offspringStatisticsDatumsList, newStatisticsDatum)
|
||||
}
|
||||
|
||||
chartTitle := diseaseName + ": 100 Prospective Offspring Risk Scores"
|
||||
|
||||
formatYAxisValuesFunction := func(inputRiskScore float64)(string, error){
|
||||
|
||||
inputRiskScoreInt, err := helpers.FloorFloat64ToInt(inputRiskScore)
|
||||
if (err != nil){ return "", err }
|
||||
|
||||
inputRiskScoreString := helpers.ConvertIntToString(inputRiskScoreInt)
|
||||
|
||||
return inputRiskScoreString, nil
|
||||
}
|
||||
|
||||
offspringsChart, err := createCharts.CreateBarChart(chartTitle, offspringStatisticsDatumsList, formatYAxisValuesFunction, true, " Offspring")
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
return offspringsChart, nil
|
||||
}
|
||||
|
||||
offspringRiskScoresChartImage, err := getOffspringSampleRiskScoresChartImage()
|
||||
if (err != nil){
|
||||
setErrorEncounteredPage(window, err, previousPage)
|
||||
return
|
||||
}
|
||||
|
||||
viewChartFullscreenButton := getWidgetCentered(widget.NewButtonWithIcon("View Fullscreen", theme.ZoomInIcon(), func(){
|
||||
setViewFullpageImagePage(window, offspringRiskScoresChartImage, currentPage)
|
||||
}))
|
||||
|
||||
pageHeader := container.NewVBox(title, backButton, widget.NewSeparator(), descriptionRow, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), numberOfLociTestedRow, widget.NewSeparator())
|
||||
|
||||
chartFyneImage := canvas.NewImageFromImage(offspringRiskScoresChartImage)
|
||||
chartFyneImage.FillMode = canvas.ImageFillContain
|
||||
|
||||
page := container.NewBorder(pageHeader, viewChartFullscreenButton, nil, nil, chartFyneImage)
|
||||
|
||||
setPageContent(page, window)
|
||||
}
|
||||
|
||||
|
||||
func setViewCoupleGeneticAnalysisTraitsPage(window fyne.Window, person1Name string, person2Name string, person1AnalysisObject geneticAnalysis.PersonAnalysis, person2AnalysisObject geneticAnalysis.PersonAnalysis, coupleAnalysisObject geneticAnalysis.CoupleAnalysis, previousPage func()){
|
||||
|
||||
|
|
|
@ -935,7 +935,7 @@ func setViewPersonGeneticAnalysisPolygenicDiseasesPage(window fyne.Window, perso
|
|||
|
||||
diseaseNameText := getBoldLabelCentered(diseaseName)
|
||||
|
||||
personRiskScoreKnown, _, personRiskScoreFormatted, _, conflictExists, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(analysisObject, diseaseName, mainGenomeIdentifier)
|
||||
personRiskScoreKnown, _, personRiskScoreFormatted, _, _, conflictExists, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(analysisObject, diseaseName, mainGenomeIdentifier)
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
getPersonRiskScoreLabelText := func()string{
|
||||
|
@ -1096,7 +1096,7 @@ func setViewPersonGeneticAnalysisPolygenicDiseaseDetailsPage(window fyne.Window,
|
|||
|
||||
genomeNameCell := getGenomeNameCell()
|
||||
|
||||
diseaseRiskScoreKnown, _, diseaseRiskScoreFormatted, numberOfLociTested, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(analysisObject, diseaseName, genomeIdentifier)
|
||||
diseaseRiskScoreKnown, _, diseaseRiskScoreFormatted, _, numberOfLociTested, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(analysisObject, diseaseName, genomeIdentifier)
|
||||
if (err != nil) { return err }
|
||||
|
||||
getRiskScoreLabelText := func()string{
|
||||
|
@ -1418,7 +1418,7 @@ func setViewPersonGenomePolygenicDiseaseLociPage(window fyne.Window, geneticAnal
|
|||
return
|
||||
}
|
||||
|
||||
locusRiskWeightIsKnown, genomeLocusRiskWeight, _, _, _, _, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, locusIdentifier, genomeIdentifier)
|
||||
locusRiskWeightIsKnown, genomeLocusRiskWeight, _, _, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, locusIdentifier, genomeIdentifier)
|
||||
if (err != nil) {
|
||||
setErrorEncounteredPage(window, err, previousPage)
|
||||
return
|
||||
|
@ -1484,7 +1484,7 @@ func setViewPersonGenomePolygenicDiseaseLociPage(window fyne.Window, geneticAnal
|
|||
locusIdentifier, err := encoding.DecodeHexStringTo3ByteArray(locusIdentifierHex)
|
||||
if (err != nil) { return err }
|
||||
|
||||
locusRiskWeightIsKnown, genomeLocusRiskWeight, _, _, locusOddsRatioIsKnown, _, locusOddsRatioFormatted, err := readGeneticAnalysis.GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, locusIdentifier, genomeIdentifier)
|
||||
locusRiskWeightIsKnown, genomeLocusRiskWeight, locusOddsRatioIsKnown, _, locusOddsRatioFormatted, err := readGeneticAnalysis.GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, locusIdentifier, genomeIdentifier)
|
||||
if (err != nil) { return err }
|
||||
|
||||
getGenomeLocusRiskWeightText := func()string{
|
||||
|
@ -1635,7 +1635,7 @@ func setViewPersonGeneticAnalysisPolygenicDiseaseLocusDetailsPage(window fyne.Wi
|
|||
|
||||
addGenomeRow := func(genomeName string, genomeIdentifier [16]byte, isACombinedGenome bool)error{
|
||||
|
||||
genomeRiskWeightKnown, genomeRiskWeight, _, _, genomeOddsRatioKnown, _, genomeOddsRatioFormatted, err := readGeneticAnalysis.GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, locusIdentifier, genomeIdentifier)
|
||||
genomeRiskWeightKnown, genomeRiskWeight, genomeOddsRatioIsKnown, _, genomeOddsRatioFormatted, err := readGeneticAnalysis.GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(geneticAnalysisObject, diseaseName, locusIdentifier, genomeIdentifier)
|
||||
if (err != nil) { return err }
|
||||
|
||||
getGenomeRiskWeightText := func()string{
|
||||
|
@ -1654,7 +1654,7 @@ func setViewPersonGeneticAnalysisPolygenicDiseaseLocusDetailsPage(window fyne.Wi
|
|||
|
||||
getGenomeOddsRatioText := func()string{
|
||||
|
||||
if (genomeOddsRatioKnown == false){
|
||||
if (genomeOddsRatioIsKnown == false){
|
||||
result := translate("Unknown")
|
||||
|
||||
return result
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -77,155 +77,20 @@ func SignInToAppUser(userName string, startBackgroundJobs bool)error{
|
|||
|
||||
appMemory.SetMemoryEntry("AppUser", userName)
|
||||
|
||||
userDirectoryPath, err := localFilesystem.GetAppUserFolderPath()
|
||||
err := createAppUserDataFolders()
|
||||
if (err != nil) { return err }
|
||||
|
||||
_, err = localFilesystem.CreateFolder(userDirectoryPath)
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myMap.InitializeMyMapsFolder()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myList.InitializeMyListsFolder()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myMapList.InitializeMyMapListsFolder()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = mySeedPhrases.InitializeMySeedPhrasesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myBroadcasts.InitializeMyBroadcastsFolders()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myLocalDesires.InitializeMyDesiresDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myMateCriteria.InitializeMyCriteriaDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myMatchScore.InitializeMyMatchScorePointsDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = mySettings.InitializeMySettingsDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myLocalProfiles.InitializeMyLocalProfileDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myMatches.InitializeMyMatchesDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myContacts.InitializeMyContactDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myIgnoredUsers.InitializeMyIgnoredUsersDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myBlockedUsers.InitializeMyBlockedUsersDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = mySecretInboxes.InitializeMySecretInboxesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myChatKeys.InitializeMyChatKeysDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myCipherKeys.InitializeMyMessageCipherKeysDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myReadStatus.InitializeMyReadStatusDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myConversationIndexes.InitializeMyConversationIndexesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myChatFilters.InitializeMyChatFiltersDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myLikedUsers.InitializeMyLikedUsersDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myChatConversations.InitializeMyChatConversationsDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myChatMessages.InitializeMyChatMessageDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myMessageQueue.InitializeMyMessageQueueDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = peerChatKeys.InitializePeerChatKeysDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = peerSecretInboxes.InitializePeerSecretInboxesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = peerDevices.InitializePeerDevicesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = sendMessages.InitializeSentMessagesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myGenomes.InitializeMyGenomeDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myGenomes.CreateUserGenomesFolder()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myPeople.InitializeMyGenomePeopleDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myCouples.InitializeMyGenomeCouplesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myAnalyses.InitializeMyAnalysesDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myAnalyses.CreateMyAnalysesFolder()
|
||||
err = initializeAppUserDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myAnalyses.PruneOldAnalyses()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = viewedContent.InitializeViewedContentDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = logger.InitializeMyLogDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = viewedModerators.InitializeViewedModeratorsDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = viewedHosts.InitializeViewedHostsDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = mySkippedContent.InitializeMySkippedContentDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myHiddenContent.InitializeMyHiddenContentDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
if (applicationVariablesInitialized == false){
|
||||
|
||||
// This only needs to be done once per application startup
|
||||
|
||||
err := worldLocations.InitializeWorldLocationsVariables()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = worldLanguages.InitializeWorldLanguageVariables()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = locusMetadata.InitializeLocusMetadataVariables()
|
||||
if (err != nil) { return err }
|
||||
|
||||
monogenicDiseases.InitializeMonogenicDiseaseVariables()
|
||||
|
||||
polygenicDiseases.InitializePolygenicDiseaseVariables()
|
||||
|
||||
traits.InitializeTraitVariables()
|
||||
|
||||
err = profileFormat.InitializeProfileFormatVariables()
|
||||
err := initializeApplicationVariables()
|
||||
if (err != nil) { return err }
|
||||
|
||||
applicationVariablesInitialized = true
|
||||
|
@ -484,7 +349,7 @@ func DeleteAppUser(userName string)(bool, error){
|
|||
// We use this to partially sign in to the first app user when testing packages that need it
|
||||
// An example is myMap, which requires an app user to be signed in to use it
|
||||
// We don't need to sign the user out after calling this function, because we only use this for testing
|
||||
func InitializeAppUserForTests()error{
|
||||
func InitializeAppUserForTests(initializeAppDatastores bool, initializeAppVariables bool)error{
|
||||
|
||||
appUsersList, err := GetAppUsersList()
|
||||
if (err != nil){ return err }
|
||||
|
@ -497,6 +362,51 @@ func InitializeAppUserForTests()error{
|
|||
|
||||
appMemory.SetMemoryEntry("AppUser", userName)
|
||||
|
||||
err = createAppUserDataFolders()
|
||||
if (err != nil) { return err }
|
||||
|
||||
if (initializeAppDatastores == true){
|
||||
|
||||
err := initializeAppUserDatastores()
|
||||
if (err != nil) { return err }
|
||||
}
|
||||
|
||||
if (initializeAppVariables == true){
|
||||
|
||||
err := initializeApplicationVariables()
|
||||
if (err != nil) { return err }
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initializeApplicationVariables()error{
|
||||
|
||||
// This only needs to be done once per application startup
|
||||
|
||||
err := worldLocations.InitializeWorldLocationsVariables()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = worldLanguages.InitializeWorldLanguageVariables()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = locusMetadata.InitializeLocusMetadataVariables()
|
||||
if (err != nil) { return err }
|
||||
|
||||
monogenicDiseases.InitializeMonogenicDiseaseVariables()
|
||||
|
||||
polygenicDiseases.InitializePolygenicDiseaseVariables()
|
||||
|
||||
traits.InitializeTraitVariables()
|
||||
|
||||
err = profileFormat.InitializeProfileFormatVariables()
|
||||
if (err != nil) { return err }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createAppUserDataFolders()error{
|
||||
|
||||
userDirectoryPath, err := localFilesystem.GetAppUserFolderPath()
|
||||
if (err != nil) { return err }
|
||||
|
||||
|
@ -512,7 +422,124 @@ func InitializeAppUserForTests()error{
|
|||
err = myMapList.InitializeMyMapListsFolder()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myBroadcasts.InitializeMyBroadcastsFolders()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myGenomes.CreateUserGenomesFolder()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myAnalyses.CreateMyAnalysesFolder()
|
||||
if (err != nil) { return err }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initializeAppUserDatastores()error{
|
||||
|
||||
err := mySeedPhrases.InitializeMySeedPhrasesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myLocalDesires.InitializeMyDesiresDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myMateCriteria.InitializeMyCriteriaDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myMatchScore.InitializeMyMatchScorePointsDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = mySettings.InitializeMySettingsDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myLocalProfiles.InitializeMyLocalProfileDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myMatches.InitializeMyMatchesDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myContacts.InitializeMyContactDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myIgnoredUsers.InitializeMyIgnoredUsersDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myBlockedUsers.InitializeMyBlockedUsersDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = mySecretInboxes.InitializeMySecretInboxesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myChatKeys.InitializeMyChatKeysDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myCipherKeys.InitializeMyMessageCipherKeysDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myReadStatus.InitializeMyReadStatusDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myConversationIndexes.InitializeMyConversationIndexesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myChatFilters.InitializeMyChatFiltersDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myLikedUsers.InitializeMyLikedUsersDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myChatConversations.InitializeMyChatConversationsDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myChatMessages.InitializeMyChatMessageDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myMessageQueue.InitializeMyMessageQueueDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = peerChatKeys.InitializePeerChatKeysDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = peerSecretInboxes.InitializePeerSecretInboxesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = peerDevices.InitializePeerDevicesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = sendMessages.InitializeSentMessagesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myGenomes.InitializeMyGenomeDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myPeople.InitializeMyGenomePeopleDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myCouples.InitializeMyGenomeCouplesDatastore()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myAnalyses.InitializeMyAnalysesDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = viewedContent.InitializeViewedContentDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = logger.InitializeMyLogDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = viewedModerators.InitializeViewedModeratorsDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = viewedHosts.InitializeViewedHostsDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = mySkippedContent.InitializeMySkippedContentDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
err = myHiddenContent.InitializeMyHiddenContentDatastores()
|
||||
if (err != nil) { return err }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
package createCharts
|
||||
|
||||
import "seekia/internal/profiles/userStatistics"
|
||||
import "seekia/internal/statisticsDatum"
|
||||
|
||||
import goChart "github.com/wcharczuk/go-chart/v2"
|
||||
import "github.com/wcharczuk/go-chart/v2/drawing"
|
||||
|
@ -15,7 +15,7 @@ import "errors"
|
|||
|
||||
// Inputs:
|
||||
// -string: Chart title
|
||||
// -[]userStatistics.StatisticsItem: Statistics items list
|
||||
// -[]statisticsDatum.StatisticsDatum: Statistics datums list
|
||||
// -func(float64)(string, error): formatYAxisValuesFunction
|
||||
// -This will take values such as 1000000 and turn them to "1 million"
|
||||
// -bool: Y-axis units exist
|
||||
|
@ -23,38 +23,38 @@ import "errors"
|
|||
// Outputs:
|
||||
// -image.Image
|
||||
// -error
|
||||
func CreateBarChart(chartTitle string, chartStatisticsItemsList []userStatistics.StatisticsItem, formatYAxisValuesFunction func(float64)(string, error), yAxisUnitsProvided bool, yAxisUnits string)(image.Image, error){
|
||||
func CreateBarChart(chartTitle string, chartStatisticsDatumsList []statisticsDatum.StatisticsDatum, formatYAxisValuesFunction func(float64)(string, error), yAxisUnitsProvided bool, yAxisUnits string)(image.Image, error){
|
||||
|
||||
if (len(chartStatisticsItemsList) == 0) {
|
||||
return nil, errors.New("CreateBarChart called with empty chartStatisticsItemsList")
|
||||
if (len(chartStatisticsDatumsList) == 0) {
|
||||
return nil, errors.New("CreateBarChart called with empty chartStatisticsDatumsList")
|
||||
}
|
||||
|
||||
chartItemsList := make([]goChart.Value, 0, len(chartStatisticsItemsList))
|
||||
chartDatumsList := make([]goChart.Value, 0, len(chartStatisticsDatumsList))
|
||||
|
||||
for _, statisticsItem := range chartStatisticsItemsList{
|
||||
for _, statisticsDatum := range chartStatisticsDatumsList{
|
||||
|
||||
itemLabel := statisticsItem.LabelFormatted
|
||||
datumLabel := statisticsDatum.LabelFormatted
|
||||
|
||||
itemValue := statisticsItem.Value
|
||||
datumValue := statisticsDatum.Value
|
||||
|
||||
// We make sure this function does not error
|
||||
_, err := formatYAxisValuesFunction(itemValue)
|
||||
_, err := formatYAxisValuesFunction(datumValue)
|
||||
if (err != nil){
|
||||
return nil, errors.New("Invalid chartStatisticsItemsList: Item value is invalid. Reason: " + err.Error())
|
||||
return nil, errors.New("Invalid chartStatisticsDatumsList: Datum value is invalid. Reason: " + err.Error())
|
||||
}
|
||||
|
||||
newChartValue := goChart.Value{
|
||||
Label: itemLabel,
|
||||
Value: itemValue,
|
||||
Label: datumLabel,
|
||||
Value: datumValue,
|
||||
}
|
||||
|
||||
chartItemsList = append(chartItemsList, newChartValue)
|
||||
chartDatumsList = append(chartDatumsList, newChartValue)
|
||||
}
|
||||
|
||||
if (len(chartItemsList) == 1){
|
||||
if (len(chartDatumsList) == 1){
|
||||
|
||||
// This package cannot create bar charts with only 1 item
|
||||
// Thus, we must add an empty item
|
||||
// This package cannot create bar charts with only 1 datum
|
||||
// Thus, we must add an empty datum
|
||||
|
||||
newChartValue := goChart.Value{
|
||||
Style: goChart.Style{
|
||||
|
@ -65,7 +65,7 @@ func CreateBarChart(chartTitle string, chartStatisticsItemsList []userStatistics
|
|||
Value: .001,
|
||||
}
|
||||
|
||||
chartItemsList = append(chartItemsList, newChartValue)
|
||||
chartDatumsList = append(chartDatumsList, newChartValue)
|
||||
}
|
||||
|
||||
chartStyleObject := goChart.Style{
|
||||
|
@ -110,7 +110,7 @@ func CreateBarChart(chartTitle string, chartStatisticsItemsList []userStatistics
|
|||
Background: chartStyleObject,
|
||||
Height: 500,
|
||||
BarWidth: 60,
|
||||
Bars: chartItemsList,
|
||||
Bars: chartDatumsList,
|
||||
YAxis: yAxisObject,
|
||||
}
|
||||
|
||||
|
@ -123,28 +123,28 @@ func CreateBarChart(chartTitle string, chartStatisticsItemsList []userStatistics
|
|||
return goImage, nil
|
||||
}
|
||||
|
||||
func CreateDonutChart(chartTitle string, chartStatisticsItemsList []userStatistics.StatisticsItem)(image.Image, error){
|
||||
func CreateDonutChart(chartTitle string, chartStatisticsDatumsList []statisticsDatum.StatisticsDatum)(image.Image, error){
|
||||
|
||||
if (len(chartStatisticsItemsList) == 0) {
|
||||
if (len(chartStatisticsDatumsList) == 0) {
|
||||
|
||||
return nil, errors.New("CreateDonutChart called with empty chartStatisticsItemsList")
|
||||
return nil, errors.New("CreateDonutChart called with empty chartStatisticsDatumsList")
|
||||
}
|
||||
|
||||
chartItemsList := make([]goChart.Value, 0, len(chartStatisticsItemsList))
|
||||
chartDatumsList := make([]goChart.Value, 0, len(chartStatisticsDatumsList))
|
||||
|
||||
for _, statisticsItem := range chartStatisticsItemsList{
|
||||
for _, statisticsDatum := range chartStatisticsDatumsList{
|
||||
|
||||
itemLabel := statisticsItem.LabelFormatted
|
||||
datumLabel := statisticsDatum.LabelFormatted
|
||||
|
||||
// Value is always a number representing the percentage of the donut
|
||||
itemValue := statisticsItem.Value
|
||||
datumValue := statisticsDatum.Value
|
||||
|
||||
newChartValue := goChart.Value{
|
||||
Label: itemLabel,
|
||||
Value: itemValue,
|
||||
Label: datumLabel,
|
||||
Value: datumValue,
|
||||
}
|
||||
|
||||
chartItemsList = append(chartItemsList, newChartValue)
|
||||
chartDatumsList = append(chartDatumsList, newChartValue)
|
||||
}
|
||||
|
||||
chartStyleObject := goChart.Style{
|
||||
|
@ -166,10 +166,10 @@ func CreateDonutChart(chartTitle string, chartStatisticsItemsList []userStatisti
|
|||
TitleStyle: titleStyleObject,
|
||||
Background: chartStyleObject,
|
||||
Height: 500,
|
||||
Values: chartItemsList,
|
||||
Values: chartDatumsList,
|
||||
}
|
||||
|
||||
if (len(chartItemsList) == 1){
|
||||
if (len(chartDatumsList) == 1){
|
||||
|
||||
// Default is transparent, we need to add color
|
||||
sliceStyleObject := goChart.Style{
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -98,6 +98,11 @@ type PersonGenomePolygenicDiseaseInfo struct{
|
|||
// This should be len(LociInfoList)
|
||||
NumberOfLociTested int
|
||||
|
||||
// This map contains the locus values for the genome for this trait
|
||||
// If an locus's entry doesn't exist, its value is unknown
|
||||
// Map Structure: Locus rsID -> Locus Value
|
||||
LocusValuesMap map[int64]locusValue.LocusValue
|
||||
|
||||
// This is total risk score for this disease for the person's genome
|
||||
// This is a number between 1-10
|
||||
RiskScore int
|
||||
|
@ -110,11 +115,6 @@ type PersonGenomePolygenicDiseaseInfo struct{
|
|||
|
||||
type PersonGenomePolygenicDiseaseLocusInfo struct{
|
||||
|
||||
// The person's genome locus base pair value for this variant's locus
|
||||
// Example: "G", "C"
|
||||
LocusBase1 string
|
||||
LocusBase2 string
|
||||
|
||||
// This is the risk weight that this person's genome has for this variant
|
||||
// A higher risk weight means more risk of getting the disease
|
||||
RiskWeight int
|
||||
|
@ -141,10 +141,10 @@ type PersonTraitInfo struct{
|
|||
|
||||
type PersonGenomeTraitInfo struct{
|
||||
|
||||
// This should be len(RulesList)
|
||||
// This should be len(GenomePassesRulesMap)
|
||||
NumberOfRulesTested int
|
||||
|
||||
// This map contains the locus values for the genome
|
||||
// This map contains the locus values for the genome for this trait
|
||||
// If an locus's entry doesn't exist, its value is unknown
|
||||
// Map Structure: Locus rsID -> Locus Value
|
||||
LocusValuesMap map[int64]locusValue.LocusValue
|
||||
|
@ -262,33 +262,38 @@ type OffspringGenomePairPolygenicDiseaseInfo struct{
|
|||
// This should be len(DiseaseLociList)
|
||||
NumberOfLociTested int
|
||||
|
||||
// A number between 1-10 representing the offspring's risk
|
||||
// A number between 1-10 representing the offspring's average risk score
|
||||
// 1 == lowest risk, 10 == highest risk
|
||||
OffspringRiskScore int
|
||||
OffspringAverageRiskScore int
|
||||
|
||||
// A map of the offspring's locus information
|
||||
// Map Structure: Locus Identifier -> OffspringPolygenicDiseaseLocusInfo
|
||||
LociInfoMap map[[3]byte]OffspringPolygenicDiseaseLocusInfo
|
||||
|
||||
// This is a list of prospective offspring risk scores
|
||||
// This is useful for plotting on a graph to understand the standard deviation of risk
|
||||
SampleOffspringRiskScoresList []int
|
||||
}
|
||||
|
||||
|
||||
type OffspringPolygenicDiseaseLocusInfo struct{
|
||||
|
||||
// This is the offspring's risk weight for this locus value
|
||||
// This is the offspring's average risk weight for this locus value
|
||||
// A higher weight means a higher risk of the disease
|
||||
OffspringRiskWeight int
|
||||
OffspringAverageRiskWeight int
|
||||
|
||||
// This is true if any of the 100 prospective offspring had a known odds ratio for this locus
|
||||
OffspringOddsRatioIsKnown bool
|
||||
|
||||
// This value represent's the offspring's average odds ratio for the disease locus
|
||||
// A value <1 denotes a lesser risk, a value >1 denotes an increased risk
|
||||
OffspringOddsRatio float64
|
||||
OffspringAverageOddsRatio float64
|
||||
|
||||
// This is the sum of weights for the loci which have no odds ratios
|
||||
// This is the average of the sum of weights for the loci which have no odds ratios for each prospective offspring
|
||||
// We do this to understand what effect those loci are having on the odds ratio
|
||||
// If the sum is <0, we say the ratio is probably lower
|
||||
// If the sum is >0, we say the ratio is probably higher
|
||||
OffspringUnknownOddsRatiosWeightSum int
|
||||
OffspringAverageUnknownOddsRatiosWeightSum int
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -482,118 +482,119 @@ func GetOffspringMonogenicDiseaseVariantInfoFromGeneticAnalysis(coupleAnalysisOb
|
|||
|
||||
|
||||
//Outputs:
|
||||
// -bool: Polygenic Disease Risk Score known
|
||||
// -int: Disease risk score
|
||||
// -string: Disease risk score formatted (has "/10" suffix)
|
||||
// -bool: Polygenic Disease Risk Score known (any loci values exist)
|
||||
// -int: Person Disease risk score
|
||||
// -string: Person Disease risk score formatted (has "/10" suffix)
|
||||
// -map[int]locusValue.LocusValue: Person locus values map
|
||||
// -int: Number of loci tested
|
||||
// -bool: Conflict exists
|
||||
// -error
|
||||
func GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(personAnalysisObject geneticAnalysis.PersonAnalysis, diseaseName string, genomeIdentifier [16]byte)(bool, int, string, int, bool, error){
|
||||
func GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(personAnalysisObject geneticAnalysis.PersonAnalysis, diseaseName string, genomeIdentifier [16]byte)(bool, int, string, map[int64]locusValue.LocusValue, int, bool, error){
|
||||
|
||||
personPolygenicDiseasesMap := personAnalysisObject.PolygenicDiseasesMap
|
||||
|
||||
personPolygenicDiseaseInfo, exists := personPolygenicDiseasesMap[diseaseName]
|
||||
if (exists == false){
|
||||
return false, 0, "", 0, false, nil
|
||||
return false, 0, "", nil, 0, false, nil
|
||||
}
|
||||
|
||||
personPolygenicDiseaseInfoMap := personPolygenicDiseaseInfo.PolygenicDiseaseInfoMap
|
||||
|
||||
genomePolygenicDiseaseInfo, exists := personPolygenicDiseaseInfoMap[genomeIdentifier]
|
||||
if (exists == false){
|
||||
return false, 0, "", 0, false, nil
|
||||
return false, 0, "", nil, 0, false, nil
|
||||
}
|
||||
|
||||
conflictExists := personPolygenicDiseaseInfo.ConflictExists
|
||||
|
||||
personDiseaseRiskScore := genomePolygenicDiseaseInfo.RiskScore
|
||||
|
||||
numberOfLociTested := genomePolygenicDiseaseInfo.NumberOfLociTested
|
||||
|
||||
personDiseaseRiskScoreString := helpers.ConvertIntToString(personDiseaseRiskScore)
|
||||
|
||||
personDiseaseRiskScoreFormatted := personDiseaseRiskScoreString + "/10"
|
||||
|
||||
return true, personDiseaseRiskScore, personDiseaseRiskScoreFormatted, numberOfLociTested, conflictExists, nil
|
||||
personLocusValuesMap := genomePolygenicDiseaseInfo.LocusValuesMap
|
||||
|
||||
numberOfLociTested := genomePolygenicDiseaseInfo.NumberOfLociTested
|
||||
|
||||
return true, personDiseaseRiskScore, personDiseaseRiskScoreFormatted, personLocusValuesMap, numberOfLociTested, conflictExists, nil
|
||||
}
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -bool: Offspring Disease Risk Score known
|
||||
// -int: Disease risk score
|
||||
// -string: Disease risk score formatted (has "/10" suffix)
|
||||
// -int: Offspring average disease risk score
|
||||
// -string: Offspring Disease average risk score formatted (has "/10" suffix)
|
||||
// -[]int: Sample Offspring Risk Scores List
|
||||
// -int: Number of loci tested
|
||||
// -bool: Conflict exists
|
||||
// -error
|
||||
func GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, genomePairIdentifier [32]byte)(bool, int, string, int, bool, error){
|
||||
func GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, genomePairIdentifier [32]byte)(bool, int, string, []int, int, bool, error){
|
||||
|
||||
couplePolygenicDiseasesMap := coupleAnalysisObject.PolygenicDiseasesMap
|
||||
|
||||
couplePolygenicDiseaseInfo, exists := couplePolygenicDiseasesMap[diseaseName]
|
||||
if (exists == false){
|
||||
return false, 0, "", 0, false, nil
|
||||
return false, 0, "", nil, 0, false, nil
|
||||
}
|
||||
|
||||
polygenicDiseaseInfoMap := couplePolygenicDiseaseInfo.PolygenicDiseaseInfoMap
|
||||
|
||||
genomePairPolygenicDiseaseInfo, exists := polygenicDiseaseInfoMap[genomePairIdentifier]
|
||||
if (exists == false){
|
||||
return false, 0, "", 0, false, nil
|
||||
return false, 0, "", nil, 0, false, nil
|
||||
}
|
||||
|
||||
conflictExists := couplePolygenicDiseaseInfo.ConflictExists
|
||||
|
||||
numberOfLociTested := genomePairPolygenicDiseaseInfo.NumberOfLociTested
|
||||
|
||||
offspringRiskScore := genomePairPolygenicDiseaseInfo.OffspringRiskScore
|
||||
offspringAverageRiskScore := genomePairPolygenicDiseaseInfo.OffspringAverageRiskScore
|
||||
|
||||
offspringRiskScoreString := helpers.ConvertIntToString(offspringRiskScore)
|
||||
offspringAverageRiskScoreString := helpers.ConvertIntToString(offspringAverageRiskScore)
|
||||
|
||||
offspringRiskScoreFormatted := offspringRiskScoreString + "/10"
|
||||
offspringAverageRiskScoreFormatted := offspringAverageRiskScoreString + "/10"
|
||||
|
||||
return true, offspringRiskScore, offspringRiskScoreFormatted, numberOfLociTested, conflictExists, nil
|
||||
sampleOffspringRiskScoresList := genomePairPolygenicDiseaseInfo.SampleOffspringRiskScoresList
|
||||
|
||||
return true, offspringAverageRiskScore, offspringAverageRiskScoreFormatted, sampleOffspringRiskScoresList, numberOfLociTested, conflictExists, nil
|
||||
}
|
||||
|
||||
//Outputs:
|
||||
// -bool: Risk Weight and base pair known
|
||||
// -int: Locus risk weight
|
||||
// -string: Locus base 1
|
||||
// -string: Locus base 2
|
||||
// -bool: Locus odds ratio known
|
||||
// -float64: Locus odds ratio
|
||||
// -string: Locus odds ratio formatted (with x suffix)
|
||||
// -error
|
||||
func GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(personAnalyisObject geneticAnalysis.PersonAnalysis, diseaseName string, locusIdentifier [3]byte, genomeIdentifier [16]byte)(bool, int, string, string, bool, float64, string, error){
|
||||
func GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(personAnalyisObject geneticAnalysis.PersonAnalysis, diseaseName string, locusIdentifier [3]byte, genomeIdentifier [16]byte)(bool, int, bool, float64, string, error){
|
||||
|
||||
personPolygenicDiseasesMap := personAnalyisObject.PolygenicDiseasesMap
|
||||
|
||||
personPolygenicDiseaseMap, exists := personPolygenicDiseasesMap[diseaseName]
|
||||
if (exists == false){
|
||||
return false, 0, "", "", false, 0, "", nil
|
||||
return false, 0, false, 0, "", nil
|
||||
}
|
||||
|
||||
personPolygenicDiseaseInfoMap := personPolygenicDiseaseMap.PolygenicDiseaseInfoMap
|
||||
|
||||
personGenomePolygenicDiseaseInfo, exists := personPolygenicDiseaseInfoMap[genomeIdentifier]
|
||||
if (exists == false){
|
||||
return false, 0, "", "", false, 0, "", nil
|
||||
return false, 0, false, 0, "", nil
|
||||
}
|
||||
|
||||
genomeLociInfoMap := personGenomePolygenicDiseaseInfo.LociInfoMap
|
||||
|
||||
locusInfoObject, exists := genomeLociInfoMap[locusIdentifier]
|
||||
if (exists == false){
|
||||
return false, 0, "", "", false, 0, "", nil
|
||||
return false, 0, false, 0, "", nil
|
||||
}
|
||||
|
||||
locusRiskWeight := locusInfoObject.RiskWeight
|
||||
|
||||
locusBase1 := locusInfoObject.LocusBase1
|
||||
locusBase2 := locusInfoObject.LocusBase2
|
||||
|
||||
locusOddsRatioIsKnown := locusInfoObject.OddsRatioIsKnown
|
||||
if (locusOddsRatioIsKnown == false){
|
||||
return true, locusRiskWeight, locusBase1, locusBase2, false, 0, "", nil
|
||||
return true, locusRiskWeight, false, 0, "", nil
|
||||
}
|
||||
|
||||
locusOddsRatio := locusInfoObject.OddsRatio
|
||||
|
@ -602,7 +603,7 @@ func GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(personAnalyisObject g
|
|||
|
||||
locusOddsRatioFormatted := genomeLocusOddsRatioString + "x"
|
||||
|
||||
return true, locusRiskWeight, locusBase1, locusBase2, true, locusOddsRatio, locusOddsRatioFormatted, nil
|
||||
return true, locusRiskWeight, true, locusOddsRatio, locusOddsRatioFormatted, nil
|
||||
}
|
||||
|
||||
//Outputs:
|
||||
|
@ -635,40 +636,40 @@ func GetOffspringPolygenicDiseaseLocusInfoFromGeneticAnalysis(coupleAnalysisObje
|
|||
return false, 0, false, 0, "", nil
|
||||
}
|
||||
|
||||
offspringRiskWeight := locusInfoObject.OffspringRiskWeight
|
||||
offspringAverageRiskWeight := locusInfoObject.OffspringAverageRiskWeight
|
||||
offspringOddsRatioIsKnown := locusInfoObject.OffspringOddsRatioIsKnown
|
||||
|
||||
if (offspringOddsRatioIsKnown == false){
|
||||
return true, offspringRiskWeight, false, 0, "", nil
|
||||
return true, offspringAverageRiskWeight, false, 0, "", nil
|
||||
}
|
||||
|
||||
offspringOddsRatio := locusInfoObject.OffspringOddsRatio
|
||||
offspringAverageOddsRatio := locusInfoObject.OffspringAverageOddsRatio
|
||||
|
||||
getOddsRatioFormatted := func()string{
|
||||
|
||||
offspringUnknownOddsRatiosWeightSum := locusInfoObject.OffspringUnknownOddsRatiosWeightSum
|
||||
offspringAverageUnknownOddsRatiosWeightSum := locusInfoObject.OffspringAverageUnknownOddsRatiosWeightSum
|
||||
|
||||
offspringOddsRatioString := helpers.ConvertFloat64ToStringRounded(offspringOddsRatio, 2)
|
||||
offspringAverageOddsRatioString := helpers.ConvertFloat64ToStringRounded(offspringAverageOddsRatio, 2)
|
||||
|
||||
if (offspringUnknownOddsRatiosWeightSum == 0){
|
||||
result := offspringOddsRatioString + "x"
|
||||
if (offspringAverageUnknownOddsRatiosWeightSum == 0){
|
||||
result := offspringAverageOddsRatioString + "x"
|
||||
|
||||
return result
|
||||
}
|
||||
if (offspringUnknownOddsRatiosWeightSum < 0){
|
||||
result := "<" + offspringOddsRatioString + "x"
|
||||
if (offspringAverageUnknownOddsRatiosWeightSum < 0){
|
||||
result := "<" + offspringAverageOddsRatioString + "x"
|
||||
|
||||
return result
|
||||
}
|
||||
// offspringUnknownOddsRatiosWeightSum > 0
|
||||
result := offspringOddsRatioString + "x+"
|
||||
// offspringAverageUnknownOddsRatiosWeightSum > 0
|
||||
result := offspringAverageOddsRatioString + "x+"
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
oddsRatioFormatted := getOddsRatioFormatted()
|
||||
|
||||
return true, offspringRiskWeight, true, offspringOddsRatio, oddsRatioFormatted, nil
|
||||
return true, offspringAverageRiskWeight, true, offspringAverageOddsRatio, oddsRatioFormatted, nil
|
||||
}
|
||||
|
||||
//Outputs:
|
||||
|
@ -858,7 +859,7 @@ func VerifyPersonGeneticAnalysis(personAnalysisObject geneticAnalysis.PersonAnal
|
|||
|
||||
for _, genomeIdentifier := range allGenomeIdentifiersList{
|
||||
|
||||
_, _, _, _, _, err := GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(personAnalysisObject, diseaseName, genomeIdentifier)
|
||||
_, _, _, _, _, _, err := GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(personAnalysisObject, diseaseName, genomeIdentifier)
|
||||
if (err != nil) { return err }
|
||||
}
|
||||
|
||||
|
@ -873,7 +874,7 @@ func VerifyPersonGeneticAnalysis(personAnalysisObject geneticAnalysis.PersonAnal
|
|||
|
||||
for _, genomeIdentifier := range allGenomeIdentifiersList{
|
||||
|
||||
_, _, _, _, _, _, _, err := GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(personAnalysisObject, diseaseName, locusIdentifier, genomeIdentifier)
|
||||
_, _, _, _, _, err := GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(personAnalysisObject, diseaseName, locusIdentifier, genomeIdentifier)
|
||||
if (err != nil) { return err }
|
||||
}
|
||||
}
|
||||
|
@ -970,7 +971,7 @@ func VerifyCoupleGeneticAnalysis(coupleAnalysisObject geneticAnalysis.CoupleAnal
|
|||
|
||||
for _, genomePairIdentifier := range allGenomePairIdentifiersList{
|
||||
|
||||
_, _, _, _, _, err := GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, genomePairIdentifier)
|
||||
_, _, _, _, _, _, err := GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, genomePairIdentifier)
|
||||
if (err != nil) { return err }
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -14,7 +14,7 @@ func TestBlockUnblockUser(t *testing.T){
|
|||
t.Fatalf("Failed to initialize app datastores: " + err.Error())
|
||||
}
|
||||
|
||||
err = appUsers.InitializeAppUserForTests()
|
||||
err = appUsers.InitializeAppUserForTests(false, false)
|
||||
if (err != nil){
|
||||
t.Fatalf("Failed to initialize app user for tests: " + err.Error())
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ func TestMyList(t *testing.T){
|
|||
if (err != nil){
|
||||
t.Fatalf("Failed to initialize app datastores: " + err.Error())
|
||||
}
|
||||
err = appUsers.InitializeAppUserForTests()
|
||||
err = appUsers.InitializeAppUserForTests(false, false)
|
||||
if (err != nil){
|
||||
t.Fatalf("Failed to initalize app user for tests: " + err.Error())
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ func TestMyMap(t *testing.T) {
|
|||
if (err != nil){
|
||||
t.Fatalf("Failed to initialize app datastores: " + err.Error())
|
||||
}
|
||||
err = appUsers.InitializeAppUserForTests()
|
||||
err = appUsers.InitializeAppUserForTests(false, false)
|
||||
if (err != nil){
|
||||
t.Fatalf("Failed to initalize app user for tests: " + err.Error())
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ func TestAddDeleteMapListData(t *testing.T) {
|
|||
if (err != nil){
|
||||
t.Fatalf("Failed to initialize app datastores: " + err.Error())
|
||||
}
|
||||
err = appUsers.InitializeAppUserForTests()
|
||||
err = appUsers.InitializeAppUserForTests(false, false)
|
||||
if (err != nil){
|
||||
t.Fatalf("Failed to initalize app user for tests: " + err.Error())
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ func TestMapListCopying(t *testing.T){
|
|||
if (err != nil){
|
||||
t.Fatalf("Failed to initialize app datastores: " + err.Error())
|
||||
}
|
||||
err = appUsers.InitializeAppUserForTests()
|
||||
err = appUsers.InitializeAppUserForTests(false, false)
|
||||
if (err != nil){
|
||||
t.Fatalf("Failed to initalize app user for tests: " + err.Error())
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import "seekia/internal/desires/myMateDesires"
|
|||
import "seekia/internal/encoding"
|
||||
import "seekia/internal/genetics/companyAnalysis"
|
||||
import "seekia/internal/genetics/createGeneticAnalysis"
|
||||
import "seekia/internal/genetics/locusValue"
|
||||
import "seekia/internal/genetics/myChosenAnalysis"
|
||||
import "seekia/internal/genetics/readGeneticAnalysis"
|
||||
import "seekia/internal/helpers"
|
||||
|
@ -677,12 +678,10 @@ func GetAnyProfileAttributeIncludingCalculated(attributeName string, getProfileA
|
|||
|
||||
for _, diseaseObject := range polygenicDiseaseObjectsList{
|
||||
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
// Map Structure: Locus rsID -> Locus Value
|
||||
userDiseaseLocusValuesMap := make(map[int64]locusValue.LocusValue)
|
||||
|
||||
userRiskWeightSum := 0
|
||||
userMinimumPossibleRiskWeightSum := 0
|
||||
userMaximumPossibleRiskWeightSum := 0
|
||||
userNumberOfLociTested := 0
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
|
@ -690,10 +689,6 @@ func GetAnyProfileAttributeIncludingCalculated(attributeName string, getProfileA
|
|||
|
||||
locusRSIDString := helpers.ConvertInt64ToString(locusRSID)
|
||||
|
||||
locusRiskWeightsMap := locusObject.RiskWeightsMap
|
||||
locusMinimumRiskWeight := locusObject.MinimumRiskWeight
|
||||
locusMaximumRiskWeight := locusObject.MaximumRiskWeight
|
||||
|
||||
locusValueAttributeName := "LocusValue_rs" + locusRSIDString
|
||||
|
||||
userLocusBasePairExists, _, userLocusBasePair, err := getProfileAttributesFunction(locusValueAttributeName)
|
||||
|
@ -702,30 +697,30 @@ func GetAnyProfileAttributeIncludingCalculated(attributeName string, getProfileA
|
|||
continue
|
||||
}
|
||||
|
||||
userNumberOfLociTested += 1
|
||||
|
||||
userMinimumPossibleRiskWeightSum += locusMinimumRiskWeight
|
||||
userMaximumPossibleRiskWeightSum += locusMaximumRiskWeight
|
||||
|
||||
userLocusRiskWeight, exists := locusRiskWeightsMap[userLocusBasePair]
|
||||
if (exists == false){
|
||||
// We do not know the risk weight for this base pair
|
||||
// We treat this as a 0 risk weight
|
||||
} else {
|
||||
userRiskWeightSum += userLocusRiskWeight
|
||||
userLocusBase1, userLocusBase2, semicolonFound := strings.Cut(userLocusBasePair, ";")
|
||||
if (semicolonFound == false){
|
||||
return false, 0, "", errors.New("Database corrupt: Contains profile with invalid " + locusValueAttributeName + " value: " + userLocusBasePair)
|
||||
}
|
||||
|
||||
userLocusValue := locusValue.LocusValue{
|
||||
Base1Value: userLocusBase1,
|
||||
Base2Value: userLocusBase2,
|
||||
//TODO: Share LocusIsPhased information in user profiles and retrieve it into this value
|
||||
LocusIsPhased: false,
|
||||
}
|
||||
|
||||
userDiseaseLocusValuesMap[locusRSID] = userLocusValue
|
||||
}
|
||||
|
||||
if (userNumberOfLociTested == 0){
|
||||
anyLocusTested, userDiseaseRiskScore, _, _, err := createGeneticAnalysis.GetPersonGenomePolygenicDiseaseInfo(diseaseLociList, userDiseaseLocusValuesMap, true)
|
||||
if (err != nil) { return false, 0, "", err }
|
||||
if (anyLocusTested == false){
|
||||
continue
|
||||
}
|
||||
|
||||
numberOfDiseasesTested += 1
|
||||
|
||||
userDiseaseRiskScore, err := helpers.ScaleNumberProportionally(true, userRiskWeightSum, userMinimumPossibleRiskWeightSum, userMaximumPossibleRiskWeightSum, 0, 100)
|
||||
if (err != nil) { return false, 0, "", err }
|
||||
|
||||
userRiskScoreFraction := float64(userDiseaseRiskScore)/float64(100)
|
||||
userRiskScoreFraction := float64(userDiseaseRiskScore)/float64(10)
|
||||
|
||||
allDiseasesAverageRiskScoreNumerator += userRiskScoreFraction
|
||||
}
|
||||
|
@ -787,35 +782,20 @@ func GetAnyProfileAttributeIncludingCalculated(attributeName string, getProfileA
|
|||
diseaseName := diseaseObject.DiseaseName
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
|
||||
offspringRiskWeightSum := 0
|
||||
offspringMinimumPossibleRiskWeightSum := 0
|
||||
offspringMaximumPossibleRiskWeightSum := 0
|
||||
offspringNumberOfLociTested := 0
|
||||
_, _, _, myDiseaseLocusValuesMap, _, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(myGeneticAnalysisObject, diseaseName, myGenomeIdentifier)
|
||||
if (err != nil) { return false, 0, "", err }
|
||||
|
||||
// Map Structure: rsID -> Locus Value
|
||||
userDiseaseLocusValuesMap := make(map[int64]locusValue.LocusValue)
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
locusIdentifierHex := locusObject.LocusIdentifier
|
||||
|
||||
locusIdentifier, err := encoding.DecodeHexStringTo3ByteArray(locusIdentifierHex)
|
||||
if (err != nil) { return false, 0, "", err }
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
|
||||
locusRSIDString := helpers.ConvertInt64ToString(locusRSID)
|
||||
|
||||
locusRiskWeightsMap := locusObject.RiskWeightsMap
|
||||
locusOddsRatiosMap := locusObject.OddsRatiosMap
|
||||
locusMinimumRiskWeight := locusObject.MinimumRiskWeight
|
||||
locusMaximumRiskWeight := locusObject.MaximumRiskWeight
|
||||
|
||||
locusValueAttributeName := "LocusValue_rs" + locusRSIDString
|
||||
|
||||
myLocusInfoIsKnown, _, myLocusBase1, myLocusBase2, _, _, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(myGeneticAnalysisObject, diseaseName, locusIdentifier, myGenomeIdentifier)
|
||||
if (err != nil) { return false, 0, "", err }
|
||||
if (myLocusInfoIsKnown == false){
|
||||
continue
|
||||
}
|
||||
|
||||
userLocusBasePairExists, _, userLocusBasePair, err := getProfileAttributesFunction(locusValueAttributeName)
|
||||
if (err != nil) { return false, 0, "", err }
|
||||
if (userLocusBasePairExists == false){
|
||||
|
@ -827,27 +807,25 @@ func GetAnyProfileAttributeIncludingCalculated(attributeName string, getProfileA
|
|||
return false, 0, "", errors.New("GetAnyProfileAttributeIncludingCalculated called with profile containing invalid " + locusValueAttributeName + ": " + userLocusBasePair)
|
||||
}
|
||||
|
||||
offspringLocusRiskWeight, _, _, _, err := createGeneticAnalysis.GetOffspringPolygenicDiseaseLocusInfo(locusRiskWeightsMap, locusOddsRatiosMap, myLocusBase1, myLocusBase2, userLocusBase1, userLocusBase2)
|
||||
if (err != nil) { return false, 0, "", err }
|
||||
newLocusValue := locusValue.LocusValue{
|
||||
Base1Value: userLocusBase1,
|
||||
Base2Value: userLocusBase2,
|
||||
//TODO: Share locusIsPhased information in user profiles are put it here
|
||||
LocusIsPhased: false,
|
||||
}
|
||||
|
||||
offspringNumberOfLociTested += 1
|
||||
|
||||
offspringMinimumPossibleRiskWeightSum += locusMinimumRiskWeight
|
||||
offspringMaximumPossibleRiskWeightSum += locusMaximumRiskWeight
|
||||
|
||||
offspringRiskWeightSum += offspringLocusRiskWeight
|
||||
userDiseaseLocusValuesMap[locusRSID] = newLocusValue
|
||||
}
|
||||
|
||||
if (offspringNumberOfLociTested == 0){
|
||||
anyLocusValuesTested, offspringAverageRiskScore, _, err := createGeneticAnalysis.GetOffspringPolygenicDiseaseInfo_Fast(diseaseLociList, myDiseaseLocusValuesMap, userDiseaseLocusValuesMap)
|
||||
if (err != nil) { return false, 0, "", err }
|
||||
if (anyLocusValuesTested == false){
|
||||
continue
|
||||
}
|
||||
|
||||
numberOfDiseasesTested += 1
|
||||
|
||||
offspringRiskScore, err := helpers.ScaleNumberProportionally(true, offspringRiskWeightSum, offspringMinimumPossibleRiskWeightSum, offspringMaximumPossibleRiskWeightSum, 0, 100)
|
||||
if (err != nil) { return false, 0, "", err }
|
||||
|
||||
offspringRiskScoreFraction := float64(offspringRiskScore)/float64(100)
|
||||
offspringRiskScoreFraction := float64(offspringAverageRiskScore)/float64(10)
|
||||
|
||||
allDiseasesAverageRiskScoreNumerator += offspringRiskScoreFraction
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
package calculatedAttributes_test
|
||||
|
||||
import "seekia/internal/profiles/calculatedAttributes"
|
||||
|
||||
import "seekia/internal/appUsers"
|
||||
import "seekia/internal/generate"
|
||||
import "seekia/internal/identity"
|
||||
import "seekia/internal/localFilesystem"
|
||||
import "seekia/internal/profiles/readProfiles"
|
||||
|
||||
import "testing"
|
||||
|
||||
|
||||
|
||||
func TestCalculatedAttributes(t *testing.T){
|
||||
|
||||
err := localFilesystem.InitializeAppDatastores()
|
||||
if (err != nil){
|
||||
t.Fatalf("InitializeAppDatastores failed: " + err.Error())
|
||||
}
|
||||
|
||||
err = appUsers.InitializeAppUserForTests(true, true)
|
||||
if (err != nil) {
|
||||
t.Fatalf("InitializeAppUserForTests failed: " + err.Error())
|
||||
}
|
||||
|
||||
calculatedAttributesList := calculatedAttributes.GetCalculatedAttributesList()
|
||||
|
||||
for i:=0; i<100; i++{
|
||||
|
||||
identityPublicKey, identityPrivateKey, err := identity.GetNewRandomPublicPrivateIdentityKeys()
|
||||
if (err != nil){
|
||||
t.Fatalf("GetNewRandomPublicPrivateIdentityKeys failed: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
fakeProfileBytes, err := generate.GetFakeProfile("Mate", identityPublicKey, identityPrivateKey, 1)
|
||||
if (err != nil){
|
||||
t.Fatalf("GetFakeProfile failed: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
ableToRead, profileVersion, _, profileAuthor, _, _, rawProfileMap, err := readProfiles.ReadProfile(true, fakeProfileBytes)
|
||||
if (err != nil){
|
||||
t.Fatalf("ReadProfile failed: " + err.Error())
|
||||
return
|
||||
}
|
||||
if (ableToRead == false){
|
||||
t.Fatalf("ReadProfile cant read profile returned from GetFakeProfile.")
|
||||
return
|
||||
}
|
||||
|
||||
profileType, err := identity.GetIdentityTypeFromIdentityHash(profileAuthor)
|
||||
if (err != nil){
|
||||
t.Fatalf("ReadProfile returning invalid identityHash: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
getProfileAttributesFunction := func(attributeName string)(bool, int, string, error){
|
||||
|
||||
attributeExists, attributeValue, err := readProfiles.GetFormattedProfileAttributeFromRawProfileMap(rawProfileMap, attributeName)
|
||||
if (err != nil) { return false, 0, "", err }
|
||||
if (attributeExists == false){
|
||||
return false, profileVersion, "", nil
|
||||
}
|
||||
return true, profileVersion, attributeValue, nil
|
||||
}
|
||||
|
||||
for _, attributeName := range calculatedAttributesList{
|
||||
|
||||
if (profileType != "Moderator"){
|
||||
if (attributeName == "IdentityScore" || attributeName == "Controversy" || attributeName == "NumberOfReviews"){
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
_, _, _, err := calculatedAttributes.GetAnyProfileAttributeIncludingCalculated(attributeName, getProfileAttributesFunction)
|
||||
if (err != nil) {
|
||||
t.Fatalf("GetAnyProfileAttributeIncludingCalculated failed: " + err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -205,26 +205,19 @@ func UpdateMyExportedProfile(myProfileType string, networkType byte)error{
|
|||
continue
|
||||
}
|
||||
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
_, _, _, myDiseaseLocusValuesMap, _, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(myGeneticAnalysisObject, diseaseName, genomeIdentifierToShare)
|
||||
if (err != nil) { return err }
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
for rsID, locusValueObject := range myDiseaseLocusValuesMap{
|
||||
|
||||
locusIdentifierHex := locusObject.LocusIdentifier
|
||||
rsIDString := helpers.ConvertInt64ToString(rsID)
|
||||
|
||||
locusIdentifier, err := encoding.DecodeHexStringTo3ByteArray(locusIdentifierHex)
|
||||
if (err != nil) { return err }
|
||||
locusBase1 := locusValueObject.Base1Value
|
||||
locusBase2 := locusValueObject.Base2Value
|
||||
|
||||
locusValueKnown, _, locusBase1, locusBase2, _, _, _, err := readGeneticAnalysis.GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(myGeneticAnalysisObject, diseaseName, locusIdentifier, genomeIdentifierToShare)
|
||||
if (err != nil) { return err }
|
||||
if (locusValueKnown == false){
|
||||
continue
|
||||
}
|
||||
basePairValue := locusBase1 + ";" + locusBase2
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
|
||||
locusRSIDString := helpers.ConvertInt64ToString(locusRSID)
|
||||
|
||||
profileMap["LocusValue_rs" + locusRSIDString] = locusBase1 + ";" + locusBase2
|
||||
profileMap["LocusValue_rs" + rsIDString] = basePairValue
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import "seekia/internal/profiles/calculatedAttributes"
|
|||
import "seekia/internal/profiles/profileStorage"
|
||||
import "seekia/internal/profiles/attributeDisplay"
|
||||
import "seekia/internal/translation"
|
||||
import "seekia/internal/statisticsDatum"
|
||||
|
||||
import "slices"
|
||||
import "strings"
|
||||
|
@ -21,61 +22,27 @@ import "errors"
|
|||
import "math"
|
||||
|
||||
|
||||
type StatisticsItem struct{
|
||||
|
||||
// The label for the statistics item
|
||||
// For a bar chart, this represents the name of an X axis bar.
|
||||
// For a donut chart, this represents the name of a donut slice
|
||||
// Example: "Man", "100-200"
|
||||
// This will never be translated, unless it is the Unknown/No Response item, in which case
|
||||
// the label will be "Unknown"/"No Response" translated to the user's current app language
|
||||
Label string
|
||||
|
||||
// This is the formatted, human readable version of the label
|
||||
// This will be translated into the application language
|
||||
// Sometimes, the LabelFormatted will be identical to Label
|
||||
// This does not include units (Example: " days", " users")
|
||||
// Example:
|
||||
// -"1000000-2000000" -> "1 million-2 million"
|
||||
LabelFormatted string
|
||||
|
||||
// The value corresponding to the label
|
||||
// For a bar chart, this represents the Y axis value for a bar.
|
||||
// For a donut chart, this represents the value (size) of one of the donut slices
|
||||
// This will never be translated
|
||||
// For example, the value could be 500 if 500 men responded Yes.
|
||||
Value float64
|
||||
|
||||
// This is the formatted version of the value
|
||||
// This does not include units (Example: " days", " users")
|
||||
// Examples:
|
||||
// -5 -> "5/10"
|
||||
// -1500000000000 -> "1.5 trillion"
|
||||
ValueFormatted string
|
||||
}
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -int: Number of users analyzed in statistics
|
||||
// -[]StatisticsItem: Statistics items list (sorted, not grouped)
|
||||
// -[]statisticsDatum.StatisticsDatum: Statistics datums list (sorted, not grouped)
|
||||
// -bool: Grouping performed
|
||||
// -[]StatisticsItem: Grouped items list
|
||||
// -[]statisticsDatum.StatisticsDatum: Grouped datums list
|
||||
// -func(float64)(string, error): Function to format y axis values
|
||||
// -This is used because the values must be passed to the chart code as pure floats, but they must be formatted after to be human readable
|
||||
// -Example: "1000000" -> "1 million"
|
||||
// -error
|
||||
func GetUserStatisticsItemsLists_BarChart(identityType string,
|
||||
func GetUserStatisticsDatumsLists_BarChart(identityType string,
|
||||
networkType byte,
|
||||
xAxisAttribute string,
|
||||
xAxisIsNumerical bool,
|
||||
formatXAxisValuesFunction func(string)(string, error),
|
||||
xAxisUnknownLabel string,
|
||||
yAxisAttribute string)(int, []StatisticsItem, bool, []StatisticsItem, func(float64)(string, error), error){
|
||||
yAxisAttribute string)(int, []statisticsDatum.StatisticsDatum, bool, []statisticsDatum.StatisticsDatum, func(float64)(string, error), error){
|
||||
|
||||
isValid := helpers.VerifyNetworkType(networkType)
|
||||
if (isValid == false){
|
||||
networkTypeString := helpers.ConvertByteToString(networkType)
|
||||
return 0, nil, false, nil, nil, errors.New("GetUserStatisticsItemsLists_BarChart called with invalid networkType: " + networkTypeString)
|
||||
return 0, nil, false, nil, nil, errors.New("GetUserStatisticsDatumsLists_BarChart called with invalid networkType: " + networkTypeString)
|
||||
}
|
||||
|
||||
getYAxisRoundingPrecision := func()int{
|
||||
|
@ -95,16 +62,16 @@ func GetUserStatisticsItemsLists_BarChart(identityType string,
|
|||
|
||||
//Outputs:
|
||||
// -int: Total analyzed users
|
||||
// -[]StatisticsItem: Statistics items list
|
||||
// -[]statisticsDatum.StatisticsDatum: Statistics datums list
|
||||
// -map[string]int: Response Counts map (X axis attribute response -> Number of y axis responses)
|
||||
// -bool: yAxisIsAverage
|
||||
// -map[string]float64: Response Sums map (X axis attribute response -> all y axis responses summed) (If yAxisIsAverage == true)
|
||||
// -func(float64)(string, error): Function to format statistics values
|
||||
// -bool: Include a No Response/Unknown value item
|
||||
// -bool: Include a No Response/Unknown value datum
|
||||
// -This is only needed if at least 1 user did not respond to the X axis attribute on their profile.
|
||||
// -StatisticsItem: The unknown value item.
|
||||
// -statisticsDatum.StatisticsDatum: The unknown value datum.
|
||||
// -error
|
||||
getStatisticsItemsList := func()(int, []StatisticsItem, map[string]int, bool, map[string]float64, func(float64)(string, error), bool, StatisticsItem, error){
|
||||
getStatisticsDatumsList := func()(int, []statisticsDatum.StatisticsDatum, map[string]int, bool, map[string]float64, func(float64)(string, error), bool, statisticsDatum.StatisticsDatum, error){
|
||||
|
||||
//TODO: Add "Probability Of ..."
|
||||
// This will allow viewing of choice attribute probabilities
|
||||
|
@ -113,8 +80,8 @@ func GetUserStatisticsItemsLists_BarChart(identityType string,
|
|||
|
||||
if (yAxisAttribute == "Number Of Users"){
|
||||
|
||||
totalAnalyzedUsers, statisticsItemsList, responseCountsMap, numberOfUnknownValueUsers, err := getProfileAttributeCountStatisticsItemsList(identityType, networkType, xAxisAttribute, formatXAxisValuesFunction)
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, err }
|
||||
totalAnalyzedUsers, statisticsDatumsList, responseCountsMap, numberOfUnknownValueUsers, err := getProfileAttributeCountStatisticsDatumsList(identityType, networkType, xAxisAttribute, formatXAxisValuesFunction)
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, err }
|
||||
|
||||
formatValuesFunction := func(input float64)(string, error){
|
||||
|
||||
|
@ -126,23 +93,23 @@ func GetUserStatisticsItemsLists_BarChart(identityType string,
|
|||
}
|
||||
|
||||
if (numberOfUnknownValueUsers == 0){
|
||||
return totalAnalyzedUsers, statisticsItemsList, responseCountsMap, false, nil, formatValuesFunction, false, StatisticsItem{}, nil
|
||||
return totalAnalyzedUsers, statisticsDatumsList, responseCountsMap, false, nil, formatValuesFunction, false, statisticsDatum.StatisticsDatum{}, nil
|
||||
}
|
||||
|
||||
unknownValueFormatted := helpers.ConvertIntToString(numberOfUnknownValueUsers)
|
||||
|
||||
unknownItem := StatisticsItem{
|
||||
unknownDatum := statisticsDatum.StatisticsDatum{
|
||||
Label: xAxisUnknownLabel,
|
||||
LabelFormatted: xAxisUnknownLabel,
|
||||
Value: float64(numberOfUnknownValueUsers),
|
||||
ValueFormatted: unknownValueFormatted,
|
||||
}
|
||||
|
||||
return totalAnalyzedUsers, statisticsItemsList, responseCountsMap, false, nil, formatValuesFunction, true, unknownItem, nil
|
||||
return totalAnalyzedUsers, statisticsDatumsList, responseCountsMap, false, nil, formatValuesFunction, true, unknownDatum, nil
|
||||
}
|
||||
|
||||
userIdentityHashesToAnalyzeList, err := getUserIdentityHashesToAnalyzeList(identityType)
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, err }
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, err }
|
||||
|
||||
yAxisIsAverage := strings.HasPrefix(yAxisAttribute, "Average ")
|
||||
if (yAxisIsAverage == true){
|
||||
|
@ -153,68 +120,71 @@ func GetUserStatisticsItemsLists_BarChart(identityType string,
|
|||
|
||||
attributeTitle := strings.TrimPrefix(yAxisAttribute, "Average ")
|
||||
|
||||
if (attributeTitle == "Wealth"){
|
||||
return "WealthInGold"
|
||||
}
|
||||
if (attributeTitle == "23andMe Neanderthal Variants"){
|
||||
return "23andMe_NeanderthalVariants"
|
||||
}
|
||||
if (attributeTitle == "Body Fat"){
|
||||
return "BodyFat"
|
||||
}
|
||||
if (attributeTitle == "Body Muscle"){
|
||||
return "BodyMuscle"
|
||||
}
|
||||
if (attributeTitle == "Fruit Rating"){
|
||||
return "FruitRating"
|
||||
}
|
||||
if (attributeTitle == "Vegetables Rating"){
|
||||
return "VegetablesRating"
|
||||
}
|
||||
if (attributeTitle == "Nuts Rating"){
|
||||
return "NutsRating"
|
||||
}
|
||||
if (attributeTitle == "Grains Rating"){
|
||||
return "GrainsRating"
|
||||
}
|
||||
if (attributeTitle == "Dairy Rating"){
|
||||
return "DairyRating"
|
||||
}
|
||||
if (attributeTitle == "Seafood Rating"){
|
||||
return "SeafoodRating"
|
||||
}
|
||||
if (attributeTitle == "Beef Rating"){
|
||||
return "BeefRating"
|
||||
}
|
||||
if (attributeTitle == "Pork Rating"){
|
||||
return "PorkRating"
|
||||
}
|
||||
if (attributeTitle == "Poultry Rating"){
|
||||
return "PoultryRating"
|
||||
}
|
||||
if (attributeTitle == "Eggs Rating"){
|
||||
return "EggsRating"
|
||||
}
|
||||
if (attributeTitle == "Beans Rating"){
|
||||
return "BeansRating"
|
||||
}
|
||||
if (attributeTitle == "Alcohol Frequency"){
|
||||
return "AlcoholFrequency"
|
||||
}
|
||||
if (attributeTitle == "Tobacco Frequency"){
|
||||
return "TobaccoFrequency"
|
||||
}
|
||||
if (attributeTitle == "Cannabis Frequency"){
|
||||
return "CannabisFrequency"
|
||||
}
|
||||
if (attributeTitle == "Pets Rating"){
|
||||
return "PetsRating"
|
||||
}
|
||||
if (attributeTitle == "Dogs Rating"){
|
||||
return "DogsRating"
|
||||
}
|
||||
if (attributeTitle == "Cats Rating"){
|
||||
return "CatsRating"
|
||||
switch attributeTitle{
|
||||
|
||||
case "Wealth":{
|
||||
return "WealthInGold"
|
||||
}
|
||||
case "23andMe Neanderthal Variants":{
|
||||
return "23andMe_NeanderthalVariants"
|
||||
}
|
||||
case "Body Fat":{
|
||||
return "BodyFat"
|
||||
}
|
||||
case "Body Muscle":{
|
||||
return "BodyMuscle"
|
||||
}
|
||||
case "Fruit Rating":{
|
||||
return "FruitRating"
|
||||
}
|
||||
case "Vegetables Rating":{
|
||||
return "VegetablesRating"
|
||||
}
|
||||
case "Nuts Rating":{
|
||||
return "NutsRating"
|
||||
}
|
||||
case "Grains Rating":{
|
||||
return "GrainsRating"
|
||||
}
|
||||
case "Dairy Rating":{
|
||||
return "DairyRating"
|
||||
}
|
||||
case "Seafood Rating":{
|
||||
return "SeafoodRating"
|
||||
}
|
||||
case "Beef Rating":{
|
||||
return "BeefRating"
|
||||
}
|
||||
case "Pork Rating":{
|
||||
return "PorkRating"
|
||||
}
|
||||
case "Poultry Rating":{
|
||||
return "PoultryRating"
|
||||
}
|
||||
case "Eggs Rating":{
|
||||
return "EggsRating"
|
||||
}
|
||||
case "Beans Rating":{
|
||||
return "BeansRating"
|
||||
}
|
||||
case "Alcohol Frequency":{
|
||||
return "AlcoholFrequency"
|
||||
}
|
||||
case "Tobacco Frequency":{
|
||||
return "TobaccoFrequency"
|
||||
}
|
||||
case "Cannabis Frequency":{
|
||||
return "CannabisFrequency"
|
||||
}
|
||||
case "Pets Rating":{
|
||||
return "PetsRating"
|
||||
}
|
||||
case "Dogs Rating":{
|
||||
return "DogsRating"
|
||||
}
|
||||
case "Cats Rating":{
|
||||
return "CatsRating"
|
||||
}
|
||||
}
|
||||
|
||||
return attributeTitle
|
||||
|
@ -240,19 +210,19 @@ func GetUserStatisticsItemsLists_BarChart(identityType string,
|
|||
for _, userIdentityHash := range userIdentityHashesToAnalyzeList{
|
||||
|
||||
profileFound, getAnyUserAttributeValueFunction, err := getRetrieveAnyAttributeFromUserNewestProfileFunction(userIdentityHash, networkType)
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, err }
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, err }
|
||||
if (profileFound == false){
|
||||
continue
|
||||
}
|
||||
|
||||
userIsDisabled, _, _, err := getAnyUserAttributeValueFunction("Disabled")
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, err }
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, err }
|
||||
if (userIsDisabled == true){
|
||||
continue
|
||||
}
|
||||
|
||||
attributeExists, _, userAttributeToGetAverageForValue, err := getAnyUserAttributeValueFunction(attributeToGetAverageFor)
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, err }
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, err }
|
||||
if (attributeExists == false){
|
||||
// This user did not respond to the attribute we are getting the average for
|
||||
// We will not add them to the statistics maps
|
||||
|
@ -263,11 +233,11 @@ func GetUserStatisticsItemsLists_BarChart(identityType string,
|
|||
|
||||
userAttributeToGetAverageForValueFloat64, err := helpers.ConvertStringToFloat64(userAttributeToGetAverageForValue)
|
||||
if (err != nil) {
|
||||
return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, errors.New("Database corrupt: Contains invalid " + userAttributeToGetAverageForValue + " value: " + userAttributeToGetAverageForValue)
|
||||
return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, errors.New("Database corrupt: Contains invalid " + userAttributeToGetAverageForValue + " value: " + userAttributeToGetAverageForValue)
|
||||
}
|
||||
|
||||
attributeFound, _, userXAxisAttributeValue, err := getAnyUserAttributeValueFunction(xAxisAttribute)
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, err }
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, err }
|
||||
if (attributeFound == false){
|
||||
// This user did not respond to the X axis attribute
|
||||
// We calculate the average for users who do not respond and put it in its own category
|
||||
|
@ -283,18 +253,18 @@ func GetUserStatisticsItemsLists_BarChart(identityType string,
|
|||
}
|
||||
|
||||
_, _, formatYAxisValuesFunction, _, _, err := attributeDisplay.GetProfileAttributeDisplayInfo(attributeToGetAverageFor)
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, err }
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, err }
|
||||
|
||||
statisticsItemsList := make([]StatisticsItem, 0, len(responseCountsMap))
|
||||
statisticsDatumsList := make([]statisticsDatum.StatisticsDatum, 0, len(responseCountsMap))
|
||||
|
||||
for attributeResponse, responsesCount := range responseCountsMap{
|
||||
|
||||
attributeResponseFormatted, err := formatXAxisValuesFunction(attributeResponse)
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, err }
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, err }
|
||||
|
||||
allResponsesSum, exists := responseSumsMap[attributeResponse]
|
||||
if (exists == false){
|
||||
return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, errors.New("Response sums map missing attribute value")
|
||||
return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, errors.New("Response sums map missing attribute value")
|
||||
}
|
||||
|
||||
averageValue := allResponsesSum/float64(responsesCount)
|
||||
|
@ -302,16 +272,16 @@ func GetUserStatisticsItemsLists_BarChart(identityType string,
|
|||
averageValueString := helpers.ConvertFloat64ToStringRounded(averageValue, yAxisRoundingPrecision)
|
||||
|
||||
averageValueFormatted, err := formatYAxisValuesFunction(averageValueString)
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, err }
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, err }
|
||||
|
||||
newStatisticsItem := StatisticsItem{
|
||||
newStatisticsDatum := statisticsDatum.StatisticsDatum{
|
||||
Label: attributeResponse,
|
||||
LabelFormatted: attributeResponseFormatted,
|
||||
Value: averageValue,
|
||||
ValueFormatted: averageValueFormatted,
|
||||
}
|
||||
|
||||
statisticsItemsList = append(statisticsItemsList, newStatisticsItem)
|
||||
statisticsDatumsList = append(statisticsDatumsList, newStatisticsDatum)
|
||||
}
|
||||
|
||||
// We use this function to format values after grouping, if grouping is needed
|
||||
|
@ -326,111 +296,111 @@ func GetUserStatisticsItemsLists_BarChart(identityType string,
|
|||
}
|
||||
|
||||
if (numberOfUsersWithUnknownXAxisValue == 0){
|
||||
return totalAnalyzedUsers, statisticsItemsList, responseCountsMap, true, responseSumsMap, formatValuesFunction, false, StatisticsItem{}, nil
|
||||
return totalAnalyzedUsers, statisticsDatumsList, responseCountsMap, true, responseSumsMap, formatValuesFunction, false, statisticsDatum.StatisticsDatum{}, nil
|
||||
}
|
||||
|
||||
unknownResponsesAverage := usersWithUnknownXAxisValueYAxisValuesSum/float64(numberOfUsersWithUnknownXAxisValue)
|
||||
|
||||
unknownResponsesValueFormatted, err := formatValuesFunction(unknownResponsesAverage)
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, err }
|
||||
if (err != nil) { return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, err }
|
||||
|
||||
// This item represents the average value for the yAxisAttribute for users who did not respond.
|
||||
// This datum represents the average value for the yAxisAttribute for users who did not respond.
|
||||
// For example, if the xAxisAttribute is Height, and the yAxisAttribute is AverageWealth, this value
|
||||
// will represent the average wealth for users who did not provide Height on their profile.
|
||||
unknownStatisticsItem := StatisticsItem{
|
||||
unknownStatisticsDatum := statisticsDatum.StatisticsDatum{
|
||||
Label: xAxisUnknownLabel,
|
||||
LabelFormatted: xAxisUnknownLabel,
|
||||
Value: unknownResponsesAverage,
|
||||
ValueFormatted: unknownResponsesValueFormatted,
|
||||
}
|
||||
|
||||
return totalAnalyzedUsers, statisticsItemsList, responseCountsMap, true, responseSumsMap, formatValuesFunction, true, unknownStatisticsItem, nil
|
||||
return totalAnalyzedUsers, statisticsDatumsList, responseCountsMap, true, responseSumsMap, formatValuesFunction, true, unknownStatisticsDatum, nil
|
||||
}
|
||||
|
||||
return 0, nil, nil, false, nil, nil, false, StatisticsItem{}, errors.New("Invalid y-axis attribute: " + yAxisAttribute)
|
||||
return 0, nil, nil, false, nil, nil, false, statisticsDatum.StatisticsDatum{}, errors.New("Invalid y-axis attribute: " + yAxisAttribute)
|
||||
}
|
||||
|
||||
totalAnalyzedUsers, statisticsItemsList, responseCountsMap, yAxisIsAverage, responseSumsMap, formatValuesFunction, includeUnknownItem, unknownValueItem, err := getStatisticsItemsList()
|
||||
totalAnalyzedUsers, statisticsDatumsList, responseCountsMap, yAxisIsAverage, responseSumsMap, formatValuesFunction, includeUnknownDatum, unknownValueDatum, err := getStatisticsDatumsList()
|
||||
if (err != nil) { return 0, nil, false, nil, nil, err }
|
||||
|
||||
sortStatisticsItemsList(statisticsItemsList, xAxisIsNumerical)
|
||||
sortStatisticsDatumsList(statisticsDatumsList, xAxisIsNumerical)
|
||||
|
||||
// We now see if we need to group the items in the list together
|
||||
// We now see if we need to group the datums in the list together
|
||||
// We do this if there are more than 10 categories
|
||||
|
||||
if (len(statisticsItemsList) <= 10){
|
||||
if (len(statisticsDatumsList) <= 10){
|
||||
|
||||
// No grouping needed. We are done.
|
||||
|
||||
if (includeUnknownItem == true){
|
||||
statisticsItemsList = append(statisticsItemsList, unknownValueItem)
|
||||
if (includeUnknownDatum == true){
|
||||
statisticsDatumsList = append(statisticsDatumsList, unknownValueDatum)
|
||||
}
|
||||
|
||||
return totalAnalyzedUsers, statisticsItemsList, false, nil, formatValuesFunction, nil
|
||||
return totalAnalyzedUsers, statisticsDatumsList, false, nil, formatValuesFunction, nil
|
||||
}
|
||||
|
||||
groupedStatisticsItemsList, err := getStatisticsItemsListGrouped(10, statisticsItemsList, xAxisIsNumerical, responseCountsMap, yAxisIsAverage, responseSumsMap, formatValuesFunction)
|
||||
groupedStatisticsDatumsList, err := getStatisticsDatumsListGrouped(10, statisticsDatumsList, xAxisIsNumerical, responseCountsMap, yAxisIsAverage, responseSumsMap, formatValuesFunction)
|
||||
if (err != nil) { return 0, nil, false, nil, nil, err }
|
||||
|
||||
if (includeUnknownItem == true){
|
||||
statisticsItemsList = append(statisticsItemsList, unknownValueItem)
|
||||
groupedStatisticsItemsList = append(groupedStatisticsItemsList, unknownValueItem)
|
||||
if (includeUnknownDatum == true){
|
||||
statisticsDatumsList = append(statisticsDatumsList, unknownValueDatum)
|
||||
groupedStatisticsDatumsList = append(groupedStatisticsDatumsList, unknownValueDatum)
|
||||
}
|
||||
|
||||
return totalAnalyzedUsers, statisticsItemsList, true, groupedStatisticsItemsList, formatValuesFunction, nil
|
||||
return totalAnalyzedUsers, statisticsDatumsList, true, groupedStatisticsDatumsList, formatValuesFunction, nil
|
||||
}
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -int: Number of users analyzed in statistics
|
||||
// -[]StatisticsItem: Statistics items list (sorted, not grouped)
|
||||
// -[]statisticsDatum.StatisticsDatum: Statistics datums list (sorted, not grouped)
|
||||
// -bool: Grouping performed
|
||||
// -[]StatisticsItem: Grouped items list
|
||||
// -[]statisticsDatum.StatisticsDatum: Grouped datums list
|
||||
// -error
|
||||
func GetUserStatisticsItemsLists_DonutChart(identityType string,
|
||||
func GetUserStatisticsDatumsLists_DonutChart(identityType string,
|
||||
networkType byte,
|
||||
attributeToAnalyze string,
|
||||
attributeIsNumerical bool,
|
||||
formatAttributeLabelsFunction func(string)(string, error),
|
||||
unknownLabelTranslated string)(int, []StatisticsItem, bool, []StatisticsItem, error){
|
||||
unknownLabelTranslated string)(int, []statisticsDatum.StatisticsDatum, bool, []statisticsDatum.StatisticsDatum, error){
|
||||
|
||||
isValid := helpers.VerifyNetworkType(networkType)
|
||||
if (isValid == false){
|
||||
networkTypeString := helpers.ConvertByteToString(networkType)
|
||||
return 0, nil, false, nil, errors.New("GetUserStatisticsItemsLists_DonutChart called with invalid networkType: " + networkTypeString)
|
||||
return 0, nil, false, nil, errors.New("GetUserStatisticsDatumsLists_DonutChart called with invalid networkType: " + networkTypeString)
|
||||
}
|
||||
|
||||
totalAnalyzedUsers, statisticsItemsList, attributeCountsMap, numberOfUnknownResponders, err := getProfileAttributeCountStatisticsItemsList(identityType, networkType, attributeToAnalyze, formatAttributeLabelsFunction)
|
||||
totalAnalyzedUsers, statisticsDatumsList, attributeCountsMap, numberOfUnknownResponders, err := getProfileAttributeCountStatisticsDatumsList(identityType, networkType, attributeToAnalyze, formatAttributeLabelsFunction)
|
||||
if (err != nil) { return 0, nil, false, nil, err }
|
||||
|
||||
sortStatisticsItemsList(statisticsItemsList, attributeIsNumerical)
|
||||
sortStatisticsDatumsList(statisticsDatumsList, attributeIsNumerical)
|
||||
|
||||
getUnknownValueItem := func()StatisticsItem{
|
||||
getUnknownValueDatum := func()statisticsDatum.StatisticsDatum{
|
||||
|
||||
numberOfUnknownRespondersString := helpers.ConvertIntToString(numberOfUnknownResponders)
|
||||
|
||||
unknownValueItem := StatisticsItem{
|
||||
unknownValueDatum := statisticsDatum.StatisticsDatum{
|
||||
Label: unknownLabelTranslated,
|
||||
LabelFormatted: unknownLabelTranslated,
|
||||
Value: float64(numberOfUnknownResponders),
|
||||
ValueFormatted: numberOfUnknownRespondersString,
|
||||
}
|
||||
|
||||
return unknownValueItem
|
||||
return unknownValueDatum
|
||||
}
|
||||
|
||||
if (len(statisticsItemsList) <= 8){
|
||||
if (len(statisticsDatumsList) <= 8){
|
||||
|
||||
// No grouping needed.
|
||||
|
||||
if (numberOfUnknownResponders != 0){
|
||||
|
||||
unknownValueItem := getUnknownValueItem()
|
||||
unknownValueDatum := getUnknownValueDatum()
|
||||
|
||||
statisticsItemsList = append(statisticsItemsList, unknownValueItem)
|
||||
statisticsDatumsList = append(statisticsDatumsList, unknownValueDatum)
|
||||
}
|
||||
|
||||
return totalAnalyzedUsers, statisticsItemsList, false, nil, nil
|
||||
return totalAnalyzedUsers, statisticsDatumsList, false, nil, nil
|
||||
}
|
||||
|
||||
formatValuesFunction := func(input float64)(string, error){
|
||||
|
@ -443,35 +413,35 @@ func GetUserStatisticsItemsLists_DonutChart(identityType string,
|
|||
return result, nil
|
||||
}
|
||||
|
||||
groupedStatisticsItemsList, err := getStatisticsItemsListGrouped(8, statisticsItemsList, attributeIsNumerical, attributeCountsMap, false, nil, formatValuesFunction)
|
||||
groupedStatisticsDatumsList, err := getStatisticsDatumsListGrouped(8, statisticsDatumsList, attributeIsNumerical, attributeCountsMap, false, nil, formatValuesFunction)
|
||||
if (err != nil) { return 0, nil, false, nil, err }
|
||||
|
||||
if (numberOfUnknownResponders != 0){
|
||||
|
||||
unknownValueItem := getUnknownValueItem()
|
||||
unknownValueDatum := getUnknownValueDatum()
|
||||
|
||||
statisticsItemsList = append(statisticsItemsList, unknownValueItem)
|
||||
groupedStatisticsItemsList = append(groupedStatisticsItemsList, unknownValueItem)
|
||||
statisticsDatumsList = append(statisticsDatumsList, unknownValueDatum)
|
||||
groupedStatisticsDatumsList = append(groupedStatisticsDatumsList, unknownValueDatum)
|
||||
}
|
||||
|
||||
return totalAnalyzedUsers, statisticsItemsList, true, groupedStatisticsItemsList, nil
|
||||
return totalAnalyzedUsers, statisticsDatumsList, true, groupedStatisticsDatumsList, nil
|
||||
}
|
||||
|
||||
|
||||
// This function will return a statistics items list of the following format:
|
||||
// This function will return a statistics datums list of the following format:
|
||||
// "Label": Attribute name (Example: "Male")
|
||||
// "Value": The number of users who responded with the attribute (in this example: "Male")
|
||||
//
|
||||
// All users of provided identityType who are not disabled will be analyzed
|
||||
// -int: Number of analyzed users
|
||||
// -[]StatisticsItem: Statistics items list (not sorted or grouped)
|
||||
// -[]statisticsDatum.StatisticsDatum: Statistics datums list (not sorted or grouped)
|
||||
// -map[string]int: Response counts map (Response -> Number of responders)
|
||||
// -int: Number of No Response/Unknown value responders
|
||||
// -error
|
||||
func getProfileAttributeCountStatisticsItemsList(identityType string,
|
||||
func getProfileAttributeCountStatisticsDatumsList(identityType string,
|
||||
networkType byte,
|
||||
attributeName string,
|
||||
formatLabelsFunction func(string)(string, error))(int, []StatisticsItem, map[string]int, int, error){
|
||||
formatLabelsFunction func(string)(string, error))(int, []statisticsDatum.StatisticsDatum, map[string]int, int, error){
|
||||
|
||||
userIdentityHashesToAnalyzeList, err := getUserIdentityHashesToAnalyzeList(identityType)
|
||||
if (err != nil) { return 0, nil, nil, 0, err }
|
||||
|
@ -509,7 +479,7 @@ func getProfileAttributeCountStatisticsItemsList(identityType string,
|
|||
responseCountsMap[attributeValue] += 1
|
||||
}
|
||||
|
||||
statisticsItemsList := make([]StatisticsItem, 0, len(responseCountsMap))
|
||||
statisticsDatumsList := make([]statisticsDatum.StatisticsDatum, 0, len(responseCountsMap))
|
||||
|
||||
for attributeResponse, numberOfUsers := range responseCountsMap{
|
||||
|
||||
|
@ -518,88 +488,88 @@ func getProfileAttributeCountStatisticsItemsList(identityType string,
|
|||
|
||||
attributeNumberOfUsersString := helpers.ConvertIntToString(numberOfUsers)
|
||||
|
||||
newStatisticsItem := StatisticsItem{
|
||||
newStatisticsDatum := statisticsDatum.StatisticsDatum{
|
||||
Label: attributeResponse,
|
||||
LabelFormatted: attributeResponseFormatted,
|
||||
Value: float64(numberOfUsers),
|
||||
ValueFormatted: attributeNumberOfUsersString,
|
||||
}
|
||||
|
||||
statisticsItemsList = append(statisticsItemsList, newStatisticsItem)
|
||||
statisticsDatumsList = append(statisticsDatumsList, newStatisticsDatum)
|
||||
}
|
||||
|
||||
return totalAnalyzedUsers, statisticsItemsList, responseCountsMap, numberOfUnknownValueUsers, nil
|
||||
return totalAnalyzedUsers, statisticsDatumsList, responseCountsMap, numberOfUnknownValueUsers, nil
|
||||
}
|
||||
|
||||
func sortStatisticsItemsList(inputStatisticsItemsList []StatisticsItem, labelIsNumerical bool){
|
||||
func sortStatisticsDatumsList(inputStatisticsDatumsList []statisticsDatum.StatisticsDatum, labelIsNumerical bool){
|
||||
|
||||
if (len(inputStatisticsItemsList) <= 1){
|
||||
if (len(inputStatisticsDatumsList) <= 1){
|
||||
return
|
||||
}
|
||||
|
||||
if (labelIsNumerical == true){
|
||||
|
||||
// We sort the items by label values in ascending order
|
||||
// We sort the datums by label values in ascending order
|
||||
// Example: Bar chart columns are ages, in order of youngest to oldest
|
||||
|
||||
compareItemsFunction := func(itemA StatisticsItem, itemB StatisticsItem)int{
|
||||
compareDatumsFunction := func(datumA statisticsDatum.StatisticsDatum, datumB statisticsDatum.StatisticsDatum)int{
|
||||
|
||||
itemALabel := itemA.Label
|
||||
itemBLabel := itemB.Label
|
||||
datumALabel := datumA.Label
|
||||
datumBLabel := datumB.Label
|
||||
|
||||
itemAFloat64, err := helpers.ConvertStringToFloat64(itemALabel)
|
||||
datumAFloat64, err := helpers.ConvertStringToFloat64(datumALabel)
|
||||
if (err != nil) {
|
||||
panic("Invalid statistics item: Item Label is not float: " + itemALabel)
|
||||
panic("Invalid statistics datum: Datum Label is not float: " + datumALabel)
|
||||
}
|
||||
|
||||
itemBFloat64, err := helpers.ConvertStringToFloat64(itemBLabel)
|
||||
datumBFloat64, err := helpers.ConvertStringToFloat64(datumBLabel)
|
||||
if (err != nil) {
|
||||
panic("Invalid statistics item: Item Label is not float: " + itemBLabel)
|
||||
panic("Invalid statistics datum: Datum Label is not float: " + datumBLabel)
|
||||
}
|
||||
|
||||
if (itemAFloat64 == itemBFloat64){
|
||||
if (datumAFloat64 == datumBFloat64){
|
||||
return 0
|
||||
}
|
||||
|
||||
if (itemAFloat64 < itemBFloat64){
|
||||
if (datumAFloat64 < datumBFloat64){
|
||||
return -1
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
slices.SortFunc(inputStatisticsItemsList, compareItemsFunction)
|
||||
slices.SortFunc(inputStatisticsDatumsList, compareDatumsFunction)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// We sort the items by their values in descending order
|
||||
// We sort the datums by their values in descending order
|
||||
|
||||
compareItemsFunction := func(itemA StatisticsItem, itemB StatisticsItem)int{
|
||||
compareDatumsFunction := func(datum1 statisticsDatum.StatisticsDatum, datum2 statisticsDatum.StatisticsDatum)int{
|
||||
|
||||
itemAValue := itemA.Value
|
||||
itemBValue := itemB.Value
|
||||
datum1Value := datum1.Value
|
||||
datum2Value := datum2.Value
|
||||
|
||||
if (itemAValue == itemBValue){
|
||||
if (datum1Value == datum2Value){
|
||||
return 0
|
||||
}
|
||||
|
||||
if (itemAValue < itemBValue){
|
||||
if (datum1Value < datum2Value){
|
||||
return 1
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
slices.SortFunc(inputStatisticsItemsList, compareItemsFunction)
|
||||
slices.SortFunc(inputStatisticsDatumsList, compareDatumsFunction)
|
||||
}
|
||||
|
||||
// This function will group a statistics items list.
|
||||
// This function will group a statistics datums list.
|
||||
// It will group Labels and their values to fit into a specified number of groups
|
||||
// Example: "1","2","3","4" -> "1-2", "3-4"
|
||||
//Inputs:
|
||||
// -int: Maximum groups to create
|
||||
// -[]StatisticsItem: Statistics items list to group
|
||||
// -[]statisticsDatum.StatisticsDatum: Statistics datums list to group
|
||||
// -bool: Label is numerical
|
||||
// -If it is, we will group labels into groups of numbers.
|
||||
// -Otherwise, we will group all categories after the first maximumGroupsToCreate into a group called Other
|
||||
|
@ -612,27 +582,27 @@ func sortStatisticsItemsList(inputStatisticsItemsList []StatisticsItem, labelIsN
|
|||
// -Response Sums map (X-axis attribute response -> all Y-axis responses summed) (If yAxisIsAverage == true)
|
||||
// -func(float64)(string, error): This is the function we use to format the values
|
||||
//Outputs:
|
||||
// -[]StatisticsItem: Grouped statistics items list
|
||||
// -[]statisticsDatum.StatisticsDatum: Grouped statistics datums list
|
||||
// -error
|
||||
func getStatisticsItemsListGrouped(maximumGroupsToCreate int,
|
||||
inputStatisticsItemsList []StatisticsItem,
|
||||
func getStatisticsDatumsListGrouped(maximumGroupsToCreate int,
|
||||
inputStatisticsDatumsList []statisticsDatum.StatisticsDatum,
|
||||
labelIsNumerical bool,
|
||||
responseCountsMap map[string]int,
|
||||
valueIsAverage bool,
|
||||
responseSumsMap map[string]float64,
|
||||
formatValuesFunction func(float64)(string, error))([]StatisticsItem, error){
|
||||
formatValuesFunction func(float64)(string, error))([]statisticsDatum.StatisticsDatum, error){
|
||||
|
||||
if (len(inputStatisticsItemsList) <= maximumGroupsToCreate){
|
||||
return nil, errors.New("maximumGroupsToCreate is <= length of input statistics items list")
|
||||
if (len(inputStatisticsDatumsList) <= maximumGroupsToCreate){
|
||||
return nil, errors.New("maximumGroupsToCreate is <= length of input statistics datums list")
|
||||
}
|
||||
|
||||
// We deep copy the statistics items list to retain the sorted version
|
||||
// We deep copy the statistics datums list to retain the sorted version
|
||||
// We need to retain both versions because the user can view the raw or grouped data in the GUI
|
||||
|
||||
statisticsItemsList := slices.Clone(inputStatisticsItemsList)
|
||||
statisticsDatumsList := slices.Clone(inputStatisticsDatumsList)
|
||||
|
||||
// We use this function to get the new value for a group of labels
|
||||
getGroupValue := func(itemsToCombineList []StatisticsItem)(float64, error){
|
||||
getGroupValue := func(datumsToCombineList []statisticsDatum.StatisticsDatum)(float64, error){
|
||||
|
||||
// This will count the total number of users who responded with the responses within this group
|
||||
// Example: Labels are "Blue", "Green", this variable will store the number of users who responded with either Blue or Green
|
||||
|
@ -642,22 +612,22 @@ func getStatisticsItemsListGrouped(maximumGroupsToCreate int,
|
|||
// We only need to add to this sum if valueIsAverage == true
|
||||
allReponsesSummed := float64(0)
|
||||
|
||||
for _, statisticsItem := range itemsToCombineList{
|
||||
for _, statisticsDatum := range datumsToCombineList{
|
||||
|
||||
itemLabel := statisticsItem.Label
|
||||
datumLabel := statisticsDatum.Label
|
||||
|
||||
responderCount, exists := responseCountsMap[itemLabel]
|
||||
responderCount, exists := responseCountsMap[datumLabel]
|
||||
if (exists == false){
|
||||
return 0, errors.New("responseCountsMap missing label: " + itemLabel)
|
||||
return 0, errors.New("responseCountsMap missing label: " + datumLabel)
|
||||
}
|
||||
|
||||
totalRespondersCount += float64(responderCount)
|
||||
|
||||
if (valueIsAverage == true){
|
||||
|
||||
yAxisAttributeResponsesSum, exists := responseSumsMap[itemLabel]
|
||||
yAxisAttributeResponsesSum, exists := responseSumsMap[datumLabel]
|
||||
if (exists == false){
|
||||
return 0, errors.New("responseSumsMap missing label: " + itemLabel)
|
||||
return 0, errors.New("responseSumsMap missing label: " + datumLabel)
|
||||
}
|
||||
allReponsesSummed += yAxisAttributeResponsesSum
|
||||
}
|
||||
|
@ -670,9 +640,9 @@ func getStatisticsItemsListGrouped(maximumGroupsToCreate int,
|
|||
|
||||
// The value is an average
|
||||
// We need to find the average for all of the user responses for the labels in the input list
|
||||
// The Values in the inputStatisticsItemsList are averages
|
||||
// The Values in the inputStatisticsDatumsList are averages
|
||||
// We can't average out the averages, because that will not give us the true average
|
||||
// We have to use the original sums for all group items and average them
|
||||
// We have to use the original sums for all group datums and average them
|
||||
|
||||
if (totalRespondersCount == 0){
|
||||
return 0, errors.New("totalRespondersCount is 0.")
|
||||
|
@ -685,82 +655,82 @@ func getStatisticsItemsListGrouped(maximumGroupsToCreate int,
|
|||
|
||||
if (labelIsNumerical == true){
|
||||
|
||||
maximumItemsPerCategory := int(math.Ceil(float64(len(statisticsItemsList))/float64(maximumGroupsToCreate)))
|
||||
maximumDatumsPerCategory := int(math.Ceil(float64(len(statisticsDatumsList))/float64(maximumGroupsToCreate)))
|
||||
|
||||
statisticsItemsListSublists, err := helpers.SplitListIntoSublists(statisticsItemsList, maximumItemsPerCategory)
|
||||
statisticsDatumsListSublists, err := helpers.SplitListIntoSublists(statisticsDatumsList, maximumDatumsPerCategory)
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
groupedItemsList := make([]StatisticsItem, 0, len(statisticsItemsListSublists))
|
||||
groupedDatumsList := make([]statisticsDatum.StatisticsDatum, 0, len(statisticsDatumsListSublists))
|
||||
|
||||
for _, groupItemsListSublist := range statisticsItemsListSublists{
|
||||
for _, groupDatumsListSublist := range statisticsDatumsListSublists{
|
||||
|
||||
if (len(groupItemsListSublist) == 1){
|
||||
// Sometimes, a group with 1 item will be created
|
||||
if (len(groupDatumsListSublist) == 1){
|
||||
// Sometimes, a group with 1 datum will be created
|
||||
// This happens if the groups cannot be evenly divided, so there is a remainder of 1.
|
||||
// Example: 10->4 groups = 3, 3, 3, 1.
|
||||
//TODO: Prevent this from happening so groups always have more than 1 subitem
|
||||
//TODO: Prevent this from happening so groups always have more than 1 subdatum
|
||||
|
||||
groupItem := groupItemsListSublist[0]
|
||||
groupDatum := groupDatumsListSublist[0]
|
||||
|
||||
groupedItemsList = append(groupedItemsList, groupItem)
|
||||
groupedDatumsList = append(groupedDatumsList, groupDatum)
|
||||
continue
|
||||
}
|
||||
|
||||
finalIndex := len(groupItemsListSublist)-1
|
||||
finalIndex := len(groupDatumsListSublist)-1
|
||||
|
||||
initialItem := groupItemsListSublist[0]
|
||||
finalItem := groupItemsListSublist[finalIndex]
|
||||
initialDatum := groupDatumsListSublist[0]
|
||||
finalDatum := groupDatumsListSublist[finalIndex]
|
||||
|
||||
initialLabel := initialItem.Label
|
||||
initialLabelFormatted := initialItem.LabelFormatted
|
||||
initialLabel := initialDatum.Label
|
||||
initialLabelFormatted := initialDatum.LabelFormatted
|
||||
|
||||
finalLabel := finalItem.Label
|
||||
finalLabelFormatted := finalItem.LabelFormatted
|
||||
finalLabel := finalDatum.Label
|
||||
finalLabelFormatted := finalDatum.LabelFormatted
|
||||
|
||||
groupValue, err := getGroupValue(groupItemsListSublist)
|
||||
groupValue, err := getGroupValue(groupDatumsListSublist)
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
groupValueFormatted, err := formatValuesFunction(groupValue)
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
newGroupStatisticsItem := StatisticsItem{
|
||||
newGroupStatisticsDatum := statisticsDatum.StatisticsDatum{
|
||||
Label: initialLabel + "-" + finalLabel,
|
||||
LabelFormatted: initialLabelFormatted + "-" + finalLabelFormatted,
|
||||
Value: groupValue,
|
||||
ValueFormatted: groupValueFormatted,
|
||||
}
|
||||
|
||||
groupedItemsList = append(groupedItemsList, newGroupStatisticsItem)
|
||||
groupedDatumsList = append(groupedDatumsList, newGroupStatisticsDatum)
|
||||
}
|
||||
|
||||
return groupedItemsList, nil
|
||||
return groupedDatumsList, nil
|
||||
}
|
||||
|
||||
// Label is not numerical
|
||||
// We combine all categories after the first maximumGroupsToCreate into a category called Other
|
||||
|
||||
itemsToKeep := statisticsItemsList[:maximumGroupsToCreate]
|
||||
datumsToKeep := statisticsDatumsList[:maximumGroupsToCreate]
|
||||
|
||||
itemsToCombine := statisticsItemsList[maximumGroupsToCreate:]
|
||||
datumsToCombine := statisticsDatumsList[maximumGroupsToCreate:]
|
||||
|
||||
otherTranslated := translation.TranslateTextFromEnglishToMyLanguage("Other")
|
||||
|
||||
otherGroupValue, err := getGroupValue(itemsToCombine)
|
||||
otherGroupValue, err := getGroupValue(datumsToCombine)
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
otherGroupValueFormatted, err := formatValuesFunction(otherGroupValue)
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
otherGroupItem := StatisticsItem{
|
||||
otherGroupDatum := statisticsDatum.StatisticsDatum{
|
||||
Label: "Other",
|
||||
LabelFormatted: otherTranslated,
|
||||
Value: otherGroupValue,
|
||||
ValueFormatted: otherGroupValueFormatted,
|
||||
}
|
||||
|
||||
groupedStatisticsItemsList := append(itemsToKeep, otherGroupItem)
|
||||
groupedStatisticsDatumsList := append(datumsToKeep, otherGroupDatum)
|
||||
|
||||
return groupedStatisticsItemsList, nil
|
||||
return groupedStatisticsDatumsList, nil
|
||||
}
|
||||
|
||||
|
||||
|
|
39
internal/statisticsDatum/statisticsDatum.go
Normal file
39
internal/statisticsDatum/statisticsDatum.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
//statisticsDatum implements the StatisticsDatum struct
|
||||
|
||||
package statisticsDatum
|
||||
|
||||
|
||||
type StatisticsDatum struct{
|
||||
|
||||
// The label for the statistics datum
|
||||
// For a bar chart, this represents the name of an X axis bar.
|
||||
// For a donut chart, this represents the name of a donut slice
|
||||
// Example: "Man", "100-200"
|
||||
// This will never be translated, unless it is the Unknown/No Response value, in which case
|
||||
// the label will be "Unknown"/"No Response" translated to the user's current app language
|
||||
Label string
|
||||
|
||||
// This is the formatted, human readable version of the label
|
||||
// This will be translated into the application language
|
||||
// Sometimes, the LabelFormatted will be identical to Label
|
||||
// This does not include units (Example: " days", " users")
|
||||
// Example:
|
||||
// -"1000000-2000000" -> "1 million-2 million"
|
||||
LabelFormatted string
|
||||
|
||||
// The value corresponding to the label
|
||||
// For a bar chart, this represents the Y axis value for a bar.
|
||||
// For a donut chart, this represents the value (size) of one of the donut slices
|
||||
// This will never be translated
|
||||
// For example, the value could be 500 if 500 men responded Yes.
|
||||
Value float64
|
||||
|
||||
// This is the formatted version of the value
|
||||
// This does not include units (Example: " days", " users")
|
||||
// Examples:
|
||||
// -5 -> "5/10"
|
||||
// -1500000000000 -> "1.5 trillion"
|
||||
ValueFormatted string
|
||||
}
|
||||
|
|
@ -320,72 +320,75 @@ func GetLocusMetadataObjectsListByChromosome(chromosome int)([]LocusMetadata, er
|
|||
// -[]byte: File bytes
|
||||
getFileBytes := func()(bool, []byte){
|
||||
|
||||
if (chromosome == 1){
|
||||
return true, LocusMetadataFile_Chromosome1
|
||||
}
|
||||
if (chromosome == 2){
|
||||
return true, LocusMetadataFile_Chromosome2
|
||||
}
|
||||
if (chromosome == 3){
|
||||
return true, LocusMetadataFile_Chromosome3
|
||||
}
|
||||
if (chromosome == 4){
|
||||
return true, LocusMetadataFile_Chromosome4
|
||||
}
|
||||
if (chromosome == 5){
|
||||
return true, LocusMetadataFile_Chromosome5
|
||||
}
|
||||
if (chromosome == 6){
|
||||
return true, LocusMetadataFile_Chromosome6
|
||||
}
|
||||
if (chromosome == 7){
|
||||
return true, LocusMetadataFile_Chromosome7
|
||||
}
|
||||
if (chromosome == 8){
|
||||
return true, LocusMetadataFile_Chromosome8
|
||||
}
|
||||
if (chromosome == 9){
|
||||
return true, LocusMetadataFile_Chromosome9
|
||||
}
|
||||
if (chromosome == 10){
|
||||
return true, LocusMetadataFile_Chromosome10
|
||||
}
|
||||
if (chromosome == 11){
|
||||
return true, LocusMetadataFile_Chromosome11
|
||||
}
|
||||
if (chromosome == 12){
|
||||
return true, LocusMetadataFile_Chromosome12
|
||||
}
|
||||
if (chromosome == 13){
|
||||
return true, LocusMetadataFile_Chromosome13
|
||||
}
|
||||
if (chromosome == 14){
|
||||
return true, LocusMetadataFile_Chromosome14
|
||||
}
|
||||
if (chromosome == 15){
|
||||
return true, LocusMetadataFile_Chromosome15
|
||||
}
|
||||
if (chromosome == 16){
|
||||
return true, LocusMetadataFile_Chromosome16
|
||||
}
|
||||
if (chromosome == 17){
|
||||
return true, LocusMetadataFile_Chromosome17
|
||||
}
|
||||
//if (chromosome == 18){
|
||||
// return true, LocusMetadataFile_Chromosome18
|
||||
//}
|
||||
if (chromosome == 19){
|
||||
return true, LocusMetadataFile_Chromosome19
|
||||
}
|
||||
if (chromosome == 20){
|
||||
return true, LocusMetadataFile_Chromosome20
|
||||
}
|
||||
if (chromosome == 21){
|
||||
return true, LocusMetadataFile_Chromosome21
|
||||
}
|
||||
if (chromosome == 22){
|
||||
return true, LocusMetadataFile_Chromosome22
|
||||
switch chromosome{
|
||||
case 1:{
|
||||
return true, LocusMetadataFile_Chromosome1
|
||||
}
|
||||
case 2:{
|
||||
return true, LocusMetadataFile_Chromosome2
|
||||
}
|
||||
case 3:{
|
||||
return true, LocusMetadataFile_Chromosome3
|
||||
}
|
||||
case 4:{
|
||||
return true, LocusMetadataFile_Chromosome4
|
||||
}
|
||||
case 5:{
|
||||
return true, LocusMetadataFile_Chromosome5
|
||||
}
|
||||
case 6:{
|
||||
return true, LocusMetadataFile_Chromosome6
|
||||
}
|
||||
case 7:{
|
||||
return true, LocusMetadataFile_Chromosome7
|
||||
}
|
||||
case 8:{
|
||||
return true, LocusMetadataFile_Chromosome8
|
||||
}
|
||||
case 9:{
|
||||
return true, LocusMetadataFile_Chromosome9
|
||||
}
|
||||
case 10:{
|
||||
return true, LocusMetadataFile_Chromosome10
|
||||
}
|
||||
case 11:{
|
||||
return true, LocusMetadataFile_Chromosome11
|
||||
}
|
||||
case 12:{
|
||||
return true, LocusMetadataFile_Chromosome12
|
||||
}
|
||||
case 13:{
|
||||
return true, LocusMetadataFile_Chromosome13
|
||||
}
|
||||
case 14:{
|
||||
return true, LocusMetadataFile_Chromosome14
|
||||
}
|
||||
case 15:{
|
||||
return true, LocusMetadataFile_Chromosome15
|
||||
}
|
||||
case 16:{
|
||||
return true, LocusMetadataFile_Chromosome16
|
||||
}
|
||||
case 17:{
|
||||
return true, LocusMetadataFile_Chromosome17
|
||||
}
|
||||
//case 18:{
|
||||
// return true, LocusMetadataFile_Chromosome18
|
||||
//}
|
||||
case 19:{
|
||||
return true, LocusMetadataFile_Chromosome19
|
||||
}
|
||||
case 20:{
|
||||
return true, LocusMetadataFile_Chromosome20
|
||||
}
|
||||
case 21:{
|
||||
return true, LocusMetadataFile_Chromosome21
|
||||
}
|
||||
case 22:{
|
||||
return true, LocusMetadataFile_Chromosome22
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue