Implemented neural network prediction for polygenic diseases to replace old method. Added autism and homosexualness to genetic analyses.
This commit is contained in:
parent
1f30bfa71c
commit
8bc2bc01f3
50 changed files with 2716 additions and 3913 deletions
|
@ -6,6 +6,7 @@ Small and insignificant changes may not be included in this log.
|
|||
|
||||
## Unversioned Changes
|
||||
|
||||
* Implemented neural network prediction for polygenic diseases to replace old method. Added autism and homosexualness to genetic analyses. - *Simon Sarasova*
|
||||
* Increased the quantity of attributes that are extracted from the OpenSNP biobank data archive. - *Simon Sarasova*
|
||||
* Added numeric traits to genetic analyses. - *Simon Sarasova*
|
||||
* Improved Documentation.md and Future-Plans.md. - *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 | 277
|
||||
Simon Sarasova | June 13, 2023 | 278
|
|
@ -289,9 +289,9 @@ There could be several analysis methods. These analysis methods will serve as an
|
|||
|
||||
Providing an open source ancestral analysis method is essential for race aware mate discovery technology to be credibly neutral. There already exist multiple open source ancestral analysis packages.
|
||||
|
||||
### Add Custom Type Illnesses
|
||||
### Add Complex Disease Diagnosis
|
||||
|
||||
Many genetic illnesses are not able to be detected using the methods implemented in the `monogenicDiseases` or the `polygenicDiseases` packages.
|
||||
Many genetic diseases are not able to be detected using the methods implemented in the `monogenicDiseases` or the `polygenicDiseases` packages.
|
||||
|
||||
Examples include diseases such as Fragile X and Turner's Syndrome.
|
||||
|
||||
|
@ -299,11 +299,7 @@ A new format called `complexDiseases` could be created.
|
|||
|
||||
Each disease can have a function that takes in a genome map and returns a diagnosis.
|
||||
|
||||
Many of these diseases may require additional data from the raw genome files that is not included in the genome map.
|
||||
|
||||
The `ReadRawGenomeFile` function should be able to read this relevant data.
|
||||
|
||||
The GUI would also have an accompanying set of pages to display these Custom illnesses.
|
||||
The GUI would also have an accompanying set of pages to display complex diseases.
|
||||
|
||||
### Add Polygenic Disease Probability Risk
|
||||
|
||||
|
@ -313,23 +309,17 @@ Meaning, we want to tell the user the estimated probability that they will get a
|
|||
|
||||
Example: Normal risk = 5%, Your risk = 10%
|
||||
|
||||
We should be able to calculate this risk. We know the polygenic disease odds ratio of a base pair `(odds of disease with base pair)/(odds of disease with standard (common) base pair)`. We know the average probability of disease for the general population for each age period. We know the probability of each base pair for the general population.
|
||||
|
||||
This will be the most useful statistic for users trying to understand their polygenic disease risk.
|
||||
|
||||
Knowing that the probability of a particular type of cancer has increased by 10x is very different depending on the probability of getting the cancer.
|
||||
Knowing that your risk score for a particular type of cancer is 10/10 is much less useful than understanding your probability of getting the cancer.
|
||||
|
||||
If the general population probability of getting cancer X is 5%, and the user's adjusted risk is 50%, that is a significant increase. However, if the general population risk is 0.1%, and the user's adjusted risk is 1%, then the user does not need to change their behavior or worry much.
|
||||
|
||||
### Add Neural Network Genetic Predictions
|
||||
### Get Genetic Training Data
|
||||
|
||||
The current method for predicting polygenic disease risks and traits is not as informative and accurate as using neural nets.
|
||||
We use neural networks to predict traits and polygenic diseases. We have to train these networks using example training data. This training data is a collection of people's genomes and the trait/polygenic disease information for each person.
|
||||
|
||||
Our current model adds and subtracts the likelihood values of various SNPs that are reported to have an effect on polygenic diseases and traits.
|
||||
|
||||
A much better method is to train a neural net to predict traits and polygenic diseases on a large number of genes. There are methods that exist to find the set of genes that have an effect on each trait/disease. For example, height is said to be effected by ~10,000 SNPs. Many GWAS studies exist which report which genes are responsible for certain traits and diseases. These are the genes to feed into the neural net for each trait/disease. These are also the genes that users will share in their profiles. I have already started to try to build this system. See `geneticPrediction.go` for an implementation of trait prediction using neural networks, and `createCoupleGeneticAnalysis.go` for information on how offspring predictions would work.
|
||||
|
||||
This method requires training data, which is largely unavailable for public use. We need fully open training data, not data that requires registration or permission to download.
|
||||
Good training data is largely unavailable for public use. We need fully open training data, not data that requires registration or permission to download.
|
||||
|
||||
[OpenSNP.org](https://opensnp.org) is a free genomic data repository. OpenSNP relies on user submitted data, which can be falsified. OpenSNP should add a verification system so data provided by trustworthy people can be prioritized.
|
||||
|
||||
|
@ -339,10 +329,10 @@ Whoever collects the data needs to choose what data to collect from each person.
|
|||
|
||||
Some examples of data to collect:
|
||||
|
||||
* Collecting polygenic disease information would enable prediction of polygenic disease risk.
|
||||
* Collecting polygenic disease information enables prediction of polygenic disease risk.
|
||||
* Pictures and scans of participants faces would enable a genetic test for facial structure
|
||||
* Personality tests would enable prediction of personality
|
||||
* Measuring height would enable prediction of height
|
||||
* Measuring height enables prediction of height
|
||||
|
||||
These kinds of genetic tests would allow parents to choose what their offspring will look like, their personality, and their intelligence.
|
||||
|
||||
|
@ -356,10 +346,12 @@ All of this is already possible, but will become easier with the proliferation o
|
|||
|
||||
### Add more diseases and traits
|
||||
|
||||
This task entails entering disease/trait SNP data from SNPedia.com and other sources. The bases have to be flipped if the orientation on SNPedia is minus. This requires flipping G/C and A/T. At least 3 people should check any added disease SNPs to ensure accuracy.
|
||||
Adding monogenic diseases entails entering disease SNP data from SNPedia.com and other sources. The bases have to be flipped if the orientation on SNPedia is minus. This requires flipping G/C and A/T. At least 3 people should check any added disease SNPs to ensure accuracy.
|
||||
|
||||
This is a tedious data entry process with negative consequences if mistakes are made. Many users could falsely believe they have monogenic diseases, which could trigger mental health crises.
|
||||
|
||||
Adding polygenic diseases/traits requires training data and access to genome wide association studies. Seekia should also have the ability to perform genome wide association studies to find causal genes for traits.
|
||||
|
||||
### Interactive Map
|
||||
|
||||
Seekia should have an interactive world map. It would be similar to OpenStreetMaps, but with much less detail. It would only need to contain borders of countries and states as lines. It would be able to display latitude/longitude coordinates on the map as points.
|
||||
|
|
|
@ -569,7 +569,7 @@ func setPolygenicDiseaseLociExplainerPage(window fyne.Window, previousPage func(
|
|||
|
||||
description1 := getLabelCentered("Each polygenic disease has a set of associated genome loci.")
|
||||
description2 := getLabelCentered("These are locations on the genome that can be tested to determine disease risk.")
|
||||
description3 := getLabelCentered("The more loci that your genome contains, the more accurate your disease risk score will be.")
|
||||
description3 := getLabelCentered("The more loci that your genome sequence contains, the more accurate your disease risk score will be.")
|
||||
|
||||
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3)
|
||||
|
||||
|
@ -615,65 +615,6 @@ func setOffspringPolygenicDiseaseNumberOfLociTestedExplainerPage(window fyne.Win
|
|||
}
|
||||
|
||||
|
||||
func setPolygenicDiseaseLocusRiskWeightExplainerPage(window fyne.Window, previousPage func()){
|
||||
|
||||
title := getPageTitleCentered("Help - Locus Risk Weight")
|
||||
|
||||
backButton := getBackButtonCentered(previousPage)
|
||||
|
||||
subtitle := getPageSubtitleCentered("Locus Risk Weight")
|
||||
|
||||
description1 := getLabelCentered("A polygenic disease risk score is calculated by testing many locations on a genome.")
|
||||
description2 := getLabelCentered("A genome will have a risk weight for each locus.")
|
||||
description3 := getLabelCentered("A negative weight reduces the risk of the disease.")
|
||||
description4 := getLabelCentered("A positive weight increases the risk of the disease.")
|
||||
description5 := getLabelCentered("A 0 weight has no effect on the risk.")
|
||||
|
||||
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4, description5)
|
||||
|
||||
setPageContent(page, window)
|
||||
}
|
||||
|
||||
func setOffspringPolygenicDiseaseLocusRiskWeightExplainerPage(window fyne.Window, previousPage func()){
|
||||
|
||||
title := getPageTitleCentered("Help - Locus Risk Weight")
|
||||
|
||||
backButton := getBackButtonCentered(previousPage)
|
||||
|
||||
subtitle := getPageSubtitleCentered("Offspring Locus Risk Weight")
|
||||
|
||||
description1 := getLabelCentered("A polygenic disease risk score is calculated by testing many locations on a genome.")
|
||||
description2 := getLabelCentered("A genome will have a risk weight for each locus.")
|
||||
description3 := getLabelCentered("A negative weight reduces the risk of the disease.")
|
||||
description4 := getLabelCentered("A positive weight increases the risk of the disease.")
|
||||
description5 := getLabelCentered("A 0 weight has no effect on the risk.")
|
||||
description6 := getLabelCentered("An offspring's locus risk weight represents the average risk weight for all 4 possible locus outcomes.")
|
||||
|
||||
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4, description5, description6)
|
||||
|
||||
setPageContent(page, window)
|
||||
}
|
||||
|
||||
func setPolygenicDiseaseLocusRiskWeightProbabilityExplainerPage(window fyne.Window, previousPage func()){
|
||||
|
||||
title := getPageTitleCentered("Help - Risk Weight Probability")
|
||||
|
||||
backButton := getBackButtonCentered(previousPage)
|
||||
|
||||
subtitle := getPageSubtitleCentered("Locus Risk Weight Probability")
|
||||
|
||||
description1 := getLabelCentered("A polygenic disease risk score is calculated by testing many locations on a genome.")
|
||||
description2 := getLabelCentered("A genome will have a risk weight for each locus.")
|
||||
description3 := getLabelCentered("A risk weight probability describes the probability of having that risk weight.")
|
||||
description4 := getLabelCentered("For example, lets suppose a risk weight of 2 has a probability of 5%")
|
||||
description5 := getLabelCentered("This means that 5% of people will have a risk weight of 2 at this locus.")
|
||||
|
||||
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4, description5)
|
||||
|
||||
setPageContent(page, window)
|
||||
}
|
||||
|
||||
|
||||
func setDiscreteTraitNeuralNetworkPredictionExplainerPage(window fyne.Window, previousPage func()){
|
||||
|
||||
title := getPageTitleCentered("Help - Neural Network Prediction")
|
||||
|
@ -768,7 +709,7 @@ func setDiscreteTraitRulesExplainerPage(window fyne.Window, previousPage func())
|
|||
|
||||
backButton := getBackButtonCentered(previousPage)
|
||||
|
||||
subtitle := getPageSubtitleCentered("Trait Rules")
|
||||
subtitle := getPageSubtitleCentered("Discrete Trait Rules")
|
||||
|
||||
description1 := getLabelCentered("Person genetic analyses contain discrete trait analyses.")
|
||||
description2 := getLabelCentered("Discrete traits has multiple outcomes, and each outcome has an associated score.")
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,3 @@
|
|||
|
||||
package gui
|
||||
|
||||
// viewGeneticReferencesGui.go implements pages to display information about genetic diseases and traits
|
||||
|
@ -245,217 +244,6 @@ func setViewPolygenicDiseaseDetailsPage(window fyne.Window, diseaseName string,
|
|||
}
|
||||
|
||||
|
||||
func setViewPolygenicDiseaseLocusDetailsPage(window fyne.Window, diseaseName string, locusIdentifier string, previousPage func()){
|
||||
|
||||
currentPage := func(){setViewPolygenicDiseaseLocusDetailsPage(window, diseaseName, locusIdentifier, previousPage)}
|
||||
|
||||
title := getPageTitleCentered("Viewing Locus Details")
|
||||
|
||||
backButton := getBackButtonCentered(previousPage)
|
||||
|
||||
locusObject, err := polygenicDiseases.GetPolygenicDiseaseLocusObject(diseaseName, locusIdentifier)
|
||||
if (err != nil){
|
||||
setErrorEncounteredPage(window, err, previousPage)
|
||||
return
|
||||
}
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
locusReferencesMap := locusObject.References
|
||||
|
||||
locusRSIDsList := []int64{locusRSID}
|
||||
|
||||
// We add aliases to locusRSIDsList
|
||||
|
||||
anyAliasesExist, rsidAliasesList, err := locusMetadata.GetRSIDAliases(locusRSID)
|
||||
if (err != nil){
|
||||
setErrorEncounteredPage(window, err, previousPage)
|
||||
return
|
||||
}
|
||||
if (anyAliasesExist == true){
|
||||
locusRSIDsList = append(locusRSIDsList, rsidAliasesList...)
|
||||
}
|
||||
|
||||
metadataExists, locusMetadataObject, err := locusMetadata.GetLocusMetadata(locusRSID)
|
||||
if (err != nil){
|
||||
setErrorEncounteredPage(window, err, previousPage)
|
||||
return
|
||||
}
|
||||
if (metadataExists == false){
|
||||
setErrorEncounteredPage(window, errors.New("setViewPolygenicDiseaseLocusDetailsPage called with locusRSID missing from locusMetadata."), previousPage)
|
||||
return
|
||||
}
|
||||
|
||||
diseaseNameLabel := widget.NewLabel("Disease Name:")
|
||||
diseaseNameText := getBoldLabel(diseaseName)
|
||||
diseaseNameRow := container.NewHBox(layout.NewSpacer(), diseaseNameLabel, diseaseNameText, layout.NewSpacer())
|
||||
|
||||
getLocusNamesLabelText := func()string{
|
||||
|
||||
if(len(locusRSIDsList) == 1){
|
||||
return "Locus Name:"
|
||||
}
|
||||
return "Locus Names:"
|
||||
}
|
||||
|
||||
locusNamesLabelText := getLocusNamesLabelText()
|
||||
|
||||
locusRSIDStringsList := make([]string, 0, len(locusRSIDsList))
|
||||
|
||||
for _, locusRSID := range locusRSIDsList{
|
||||
|
||||
locusRSIDString := helpers.ConvertInt64ToString(locusRSID)
|
||||
|
||||
locusRSIDName := "rs" + locusRSIDString
|
||||
|
||||
locusRSIDStringsList = append(locusRSIDStringsList, locusRSIDName)
|
||||
}
|
||||
|
||||
locusNamesListString := strings.Join(locusRSIDStringsList, ", ")
|
||||
locusNamesLabel := widget.NewLabel(locusNamesLabelText)
|
||||
locusNamesText := getBoldLabel(locusNamesListString)
|
||||
locusNamesRow := container.NewHBox(layout.NewSpacer(), locusNamesLabel, locusNamesText, layout.NewSpacer())
|
||||
|
||||
getLocusGeneNameLabelValue := func()string{
|
||||
|
||||
locusGeneInfoIsKnown := locusMetadataObject.GeneInfoIsKnown
|
||||
if (locusGeneInfoIsKnown == false){
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
locusGeneExists := locusMetadataObject.GeneExists
|
||||
if (locusGeneExists == false){
|
||||
return "None"
|
||||
}
|
||||
|
||||
locusGeneName := locusMetadataObject.GeneNamesList[0]
|
||||
|
||||
return locusGeneName
|
||||
}
|
||||
|
||||
locusGeneNameLabelValue := getLocusGeneNameLabelValue()
|
||||
|
||||
geneNameLabel := widget.NewLabel("Gene Name:")
|
||||
geneNameText := getBoldLabel(locusGeneNameLabelValue)
|
||||
geneNameRow := container.NewHBox(layout.NewSpacer(), geneNameLabel, geneNameText, layout.NewSpacer())
|
||||
|
||||
viewReferencesButton := getWidgetCentered(widget.NewButtonWithIcon("View References", theme.ListIcon(), func(){
|
||||
setViewGeneticAnalysisReferencesPage(window, "Locus", locusReferencesMap, currentPage)
|
||||
}))
|
||||
|
||||
getBasePairsGrid := func()(*fyne.Container, error){
|
||||
|
||||
locusRiskWeightsMap := locusObject.RiskWeightsMap
|
||||
locusBasePairProbabilitiesMap := locusObject.BasePairProbabilitiesMap
|
||||
|
||||
riskWeightLabel := getItalicLabelCentered("Risk Weight")
|
||||
probabilityLabel := getItalicLabelCentered("Probability Of Weight")
|
||||
|
||||
riskWeightColumn := container.NewVBox(riskWeightLabel, widget.NewSeparator())
|
||||
riskWeightProbabilityColumn := container.NewVBox(probabilityLabel, widget.NewSeparator())
|
||||
|
||||
// We create a new map with duplicates removed
|
||||
|
||||
locusBasePairProbabilitiesMap_DuplicatesRemoved := make(map[string]float64)
|
||||
|
||||
for basePair, basePairProbability := range locusBasePairProbabilitiesMap{
|
||||
|
||||
baseA, baseB, semicolonFound := strings.Cut(basePair, ";")
|
||||
if (semicolonFound == false) {
|
||||
return nil, errors.New("Invalid base pair found in locusBasePairProbabilitiesMap: " + basePair)
|
||||
}
|
||||
basePairDuplicate := baseB + ";" + baseA
|
||||
|
||||
existingProbabilityValue, exists := locusBasePairProbabilitiesMap_DuplicatesRemoved[basePairDuplicate]
|
||||
if (exists == true){
|
||||
|
||||
// The duplicate has already been added.
|
||||
// We make sure the probability values match
|
||||
if (existingProbabilityValue != basePairProbability){
|
||||
return nil, errors.New("locusBasePairProbabilitiesMap contains duplicate base pair with different value")
|
||||
}
|
||||
continue
|
||||
}
|
||||
locusBasePairProbabilitiesMap_DuplicatesRemoved[basePair] = basePairProbability
|
||||
}
|
||||
|
||||
// All probabilities are mutually exclusive (you can only have 1 base pair for each genome locus)
|
||||
// Thus, we can add them together to get a total probability for each risk weight
|
||||
|
||||
// Map structure: Risk Weight -> Probability of having weight
|
||||
riskWeightProbabilitiesMap := make(map[int]float64)
|
||||
|
||||
for basePair, basePairProbability := range locusBasePairProbabilitiesMap_DuplicatesRemoved{
|
||||
|
||||
getBasePairRiskWeight := func()int{
|
||||
|
||||
basePairRiskWeight, exists := locusRiskWeightsMap[basePair]
|
||||
if (exists == false){
|
||||
// This base pair has no known weight. We treat it as a 0 weight.
|
||||
return 0
|
||||
}
|
||||
return basePairRiskWeight
|
||||
}
|
||||
|
||||
basePairRiskWeight := getBasePairRiskWeight()
|
||||
|
||||
riskWeightProbabilitiesMap[basePairRiskWeight] += basePairProbability
|
||||
}
|
||||
|
||||
// Now we sort risk weights in order of least to greatest
|
||||
allRiskWeightsList := helpers.GetListOfMapKeys(riskWeightProbabilitiesMap)
|
||||
|
||||
slices.Sort(allRiskWeightsList)
|
||||
|
||||
for _, riskWeight := range allRiskWeightsList{
|
||||
|
||||
riskWeightProbability, exists := riskWeightProbabilitiesMap[riskWeight]
|
||||
if (exists == false){
|
||||
return nil, errors.New("Risk weight probability not found in riskWeightProbabilitiesMap")
|
||||
}
|
||||
|
||||
riskWeightString := helpers.ConvertIntToString(riskWeight)
|
||||
|
||||
riskWeightPercentageProbability := riskWeightProbability * 100
|
||||
riskWeightProbabilityString := helpers.ConvertFloat64ToStringRounded(riskWeightPercentageProbability, 2)
|
||||
riskWeightProbabilityFormatted := "~" + riskWeightProbabilityString + "%"
|
||||
|
||||
riskWeightText := getBoldLabelCentered(riskWeightString)
|
||||
riskWeightProbabilityText := getBoldLabelCentered(riskWeightProbabilityFormatted)
|
||||
|
||||
riskWeightColumn.Add(riskWeightText)
|
||||
riskWeightProbabilityColumn.Add(riskWeightProbabilityText)
|
||||
|
||||
riskWeightColumn.Add(widget.NewSeparator())
|
||||
riskWeightProbabilityColumn.Add(widget.NewSeparator())
|
||||
}
|
||||
|
||||
riskWeightHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
||||
setPolygenicDiseaseLocusRiskWeightExplainerPage(window, currentPage)
|
||||
})
|
||||
riskWeightColumn.Add(riskWeightHelpButton)
|
||||
|
||||
probabilityHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
||||
setPolygenicDiseaseLocusRiskWeightProbabilityExplainerPage(window, currentPage)
|
||||
})
|
||||
riskWeightProbabilityColumn.Add(probabilityHelpButton)
|
||||
|
||||
basePairsGrid := container.NewHBox(layout.NewSpacer(), riskWeightColumn, riskWeightProbabilityColumn, layout.NewSpacer())
|
||||
|
||||
return basePairsGrid, nil
|
||||
}
|
||||
|
||||
basePairsGrid, err := getBasePairsGrid()
|
||||
if (err != nil){
|
||||
setErrorEncounteredPage(window, err, previousPage)
|
||||
return
|
||||
}
|
||||
|
||||
page := container.NewVBox(title, backButton, widget.NewSeparator(), diseaseNameRow, widget.NewSeparator(), locusNamesRow, widget.NewSeparator(), geneNameRow, widget.NewSeparator(), viewReferencesButton, widget.NewSeparator(), basePairsGrid)
|
||||
|
||||
setPageContent(page, window)
|
||||
}
|
||||
|
||||
|
||||
func setViewGeneticAnalysisReferencesPage(window fyne.Window, referencesTopic string, referencesMap map[string]string, previousPage func()){
|
||||
|
||||
currentPage := func(){setViewGeneticAnalysisReferencesPage(window, referencesTopic, referencesMap, previousPage)}
|
||||
|
@ -644,5 +432,3 @@ func setViewDiscreteTraitRuleDetailsPage(window fyne.Window, traitName string, r
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -945,9 +945,7 @@ func GetFakeProfile(profileType string, identityPublicKey [32]byte, identityPriv
|
|||
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
for _, locusRSID := range diseaseLociList{
|
||||
|
||||
shareableRSIDsMap[locusRSID] = struct{}{}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import "seekia/internal/helpers"
|
|||
|
||||
import "errors"
|
||||
import mathRand "math/rand/v2"
|
||||
import "slices"
|
||||
import "maps"
|
||||
import "reflect"
|
||||
|
||||
|
@ -512,7 +511,6 @@ func CreateCoupleGeneticAnalysis(person1GenomesList []prepareRawGenomes.RawGenom
|
|||
for _, diseaseObject := range polygenicDiseaseObjectsList{
|
||||
|
||||
diseaseName := diseaseObject.DiseaseName
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
|
||||
// This map stores the polygenic disease info for each genome pair
|
||||
// Map Structure: Genome Pair Identifier -> OffspringGenomePairPolygenicDiseaseInfo
|
||||
|
@ -532,9 +530,13 @@ func CreateCoupleGeneticAnalysis(person1GenomesList []prepareRawGenomes.RawGenom
|
|||
return errors.New("addGenomePairDiseaseInfoToDiseaseMap called with unknown person2GenomeIdentifier.")
|
||||
}
|
||||
|
||||
anyOffspringLocusTested, genomePairOffspringAverageRiskScore, quantityOfLociTested, genomePairOffspringDiseaseLociInfoMap, genomePairSampleOffspringRiskScoresList, err := GetOffspringPolygenicDiseaseInfo(diseaseLociList, person1LocusValuesMap, person2LocusValuesMap)
|
||||
neuralNetworkExists, anyOffspringLocusKnown, offspringAverageRiskScore, accuracyRangesMap, predictedRiskScoresList, quantityOfLociKnown, quantityOfParentalPhasedLoci, err := GetOffspringPolygenicDiseaseAnalysis(diseaseObject, person1LocusValuesMap, person2LocusValuesMap)
|
||||
if (err != nil) { return err }
|
||||
if (anyOffspringLocusTested == false){
|
||||
if (neuralNetworkExists == false){
|
||||
// We cannot analyze this disease
|
||||
return nil
|
||||
}
|
||||
if (anyOffspringLocusKnown == false){
|
||||
// We have no information about this genome pair's disease risk
|
||||
// We don't add this genome pair's disease info to the diseaseInfoMap
|
||||
return nil
|
||||
|
@ -542,10 +544,11 @@ func CreateCoupleGeneticAnalysis(person1GenomesList []prepareRawGenomes.RawGenom
|
|||
|
||||
newOffspringGenomePairPolygenicDiseaseInfo := geneticAnalysis.OffspringGenomePairPolygenicDiseaseInfo{
|
||||
|
||||
QuantityOfLociTested: quantityOfLociTested,
|
||||
OffspringAverageRiskScore: genomePairOffspringAverageRiskScore,
|
||||
LociInfoMap: genomePairOffspringDiseaseLociInfoMap,
|
||||
SampleOffspringRiskScoresList: genomePairSampleOffspringRiskScoresList,
|
||||
OffspringAverageRiskScore: offspringAverageRiskScore,
|
||||
PredictionConfidenceRangesMap: accuracyRangesMap,
|
||||
QuantityOfLociKnown: quantityOfLociKnown,
|
||||
QuantityOfParentalPhasedLoci: quantityOfParentalPhasedLoci,
|
||||
SampleOffspringRiskScoresList: predictedRiskScoresList,
|
||||
}
|
||||
|
||||
genomePairIdentifier := helpers.JoinTwo16ByteArrays(person1GenomeIdentifier, person2GenomeIdentifier)
|
||||
|
@ -564,6 +567,11 @@ func CreateCoupleGeneticAnalysis(person1GenomesList []prepareRawGenomes.RawGenom
|
|||
if (err != nil) { return false, "", err }
|
||||
}
|
||||
|
||||
if (len(offspringPolygenicDiseaseInfoMap) == 0){
|
||||
// No disease analysis was performed
|
||||
continue
|
||||
}
|
||||
|
||||
newOffspringPolygenicDiseaseInfoObject := geneticAnalysis.OffspringPolygenicDiseaseInfo{
|
||||
PolygenicDiseaseInfoMap: offspringPolygenicDiseaseInfoMap,
|
||||
}
|
||||
|
@ -644,7 +652,7 @@ func CreateCoupleGeneticAnalysis(person1GenomesList []prepareRawGenomes.RawGenom
|
|||
|
||||
newOffspringGenomePairTraitInfo := geneticAnalysis.OffspringGenomePairDiscreteTraitInfo{}
|
||||
|
||||
neuralNetworkExists, neuralNetworkAnalysisExists, outcomeProbabilitiesMap, averagePredictionConfidence, quantityOfLociTested, quantityOfParentalPhasedLoci, err := GetOffspringDiscreteTraitInfo_NeuralNetwork(traitObject, person1LocusValuesMap, person2LocusValuesMap)
|
||||
neuralNetworkExists, neuralNetworkAnalysisExists, outcomeProbabilitiesMap, averagePredictionConfidence, quantityOfLociTested, quantityOfParentalPhasedLoci, err := GetOffspringDiscreteTraitAnalysis_NeuralNetwork(traitObject, person1LocusValuesMap, person2LocusValuesMap)
|
||||
if (err != nil) { return err }
|
||||
if (neuralNetworkExists == true){
|
||||
|
||||
|
@ -665,7 +673,7 @@ func CreateCoupleGeneticAnalysis(person1GenomesList []prepareRawGenomes.RawGenom
|
|||
}
|
||||
}
|
||||
|
||||
anyRulesExist, rulesAnalysisExists, quantityOfRulesTested, quantityOfLociKnown, offspringProbabilityOfPassingRulesMap, offspringOutcomeProbabilitiesMap, err := GetOffspringDiscreteTraitInfo_Rules(traitObject, person1LocusValuesMap, person2LocusValuesMap)
|
||||
anyRulesExist, rulesAnalysisExists, quantityOfRulesTested, quantityOfLociKnown, offspringProbabilityOfPassingRulesMap, offspringOutcomeProbabilitiesMap, err := GetOffspringDiscreteTraitAnalysis_Rules(traitObject, person1LocusValuesMap, person2LocusValuesMap)
|
||||
if (err != nil) { return err }
|
||||
if (anyRulesExist == true){
|
||||
|
||||
|
@ -764,7 +772,7 @@ func CreateCoupleGeneticAnalysis(person1GenomesList []prepareRawGenomes.RawGenom
|
|||
return errors.New("addGenomePairTraitInfoToOffspringMap called with unknown person2GenomeIdentifier.")
|
||||
}
|
||||
|
||||
neuralNetworkExists, neuralNetworkAnalysisExists, averageOutcome, predictionConfidenceRangesMap, sampleOffspringOutcomesList, quantityOfLociTested, quantityOfParentalPhasedLoci, err := GetOffspringNumericTraitInfo(traitObject, person1LocusValuesMap, person2LocusValuesMap)
|
||||
neuralNetworkExists, neuralNetworkAnalysisExists, averageOutcome, predictionConfidenceRangesMap, sampleOffspringOutcomesList, quantityOfLociTested, quantityOfParentalPhasedLoci, err := GetOffspringNumericTraitAnalysis(traitObject, person1LocusValuesMap, person2LocusValuesMap)
|
||||
if (err != nil) { return err }
|
||||
if (neuralNetworkExists == false){
|
||||
// Predictions are not possible for this trait
|
||||
|
@ -951,288 +959,109 @@ func GetOffspringMonogenicDiseaseProbabilities(dominantOrRecessive string, perso
|
|||
return true, percentageProbabilityOffspringHasDiseaseInt, true, percentageProbabilityOffspringHasVariantInt, nil
|
||||
}
|
||||
|
||||
|
||||
// This is used to calculate user polygenic disease info for users
|
||||
// It is faster to do it this way, because we don't create 100 prospective offspring
|
||||
// We instead create 4 outcomes for each locus
|
||||
// We can do this because testing each locus's risk score is independent of every other locus
|
||||
// This is not true for traits, because trait rules are effected by multiple different loci
|
||||
// When using the fast method for polygenic diseases, we don't get a sample of 100 offspring disease risk scores.
|
||||
// The average risk score should still be the same for the fast and normal methods
|
||||
// This function is also faster because we don't calculate odds ratio information or information about each locus
|
||||
//Outputs:
|
||||
// -bool: Any loci tested (if false, no offspring polygenic disease information is known)
|
||||
// -int: Offspring Risk Score (Value between 0-10)
|
||||
// -int: Number of loci tested
|
||||
// -error
|
||||
func GetOffspringPolygenicDiseaseInfo_Fast(diseaseLociList []polygenicDiseases.DiseaseLocus, person1LocusValuesMap map[int64]locusValue.LocusValue, person2LocusValuesMap map[int64]locusValue.LocusValue)(bool, int, int, error){
|
||||
|
||||
if (len(person1LocusValuesMap) == 0){
|
||||
return false, 0, 0, nil
|
||||
}
|
||||
if (len(person2LocusValuesMap) == 0){
|
||||
return false, 0, 0, nil
|
||||
}
|
||||
|
||||
// I = Insertion
|
||||
// D = Deletion
|
||||
|
||||
validAllelesList := []string{"C", "A", "T", "G", "I", "D"}
|
||||
|
||||
numberOfLociTested := 0
|
||||
|
||||
offspringSummedRiskWeights := 0
|
||||
offspringMinimumPossibleRiskWeightSum := 0
|
||||
offspringMaximumPossibleRiskWeightSum := 0
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
locusRiskWeightsMap := locusObject.RiskWeightsMap
|
||||
locusMinimumWeight := locusObject.MinimumRiskWeight
|
||||
locusMaximumWeight := locusObject.MaximumRiskWeight
|
||||
|
||||
person1LocusValueFound, person1LocusBase1Value, person1LocusBase2Value, _, _, err := createPersonGeneticAnalysis.GetLocusValueFromGenomeMap(true, person1LocusValuesMap, locusRSID)
|
||||
if (err != nil) { return false, 0, 0, err }
|
||||
if (person1LocusValueFound == false){
|
||||
// None of the offspring will have a value for this locus
|
||||
continue
|
||||
}
|
||||
|
||||
person2LocusValueFound, person2LocusBase1Value, person2LocusBase2Value, _, _, err := createPersonGeneticAnalysis.GetLocusValueFromGenomeMap(true, person2LocusValuesMap, locusRSID)
|
||||
if (err != nil) { return false, 0, 0, err }
|
||||
if (person2LocusValueFound == false){
|
||||
// None of the offspring will have a value for this locus
|
||||
continue
|
||||
}
|
||||
|
||||
baseIsValid := slices.Contains(validAllelesList, person1LocusBase1Value)
|
||||
if (baseIsValid == false){
|
||||
return false, 0, 0, errors.New("GetOffspringPolygenicDiseaseInfo_Fast called with genomeMap containing invalid locus value base: " + person1LocusBase1Value)
|
||||
}
|
||||
baseIsValid = slices.Contains(validAllelesList, person1LocusBase2Value)
|
||||
if (baseIsValid == false){
|
||||
return false, 0, 0, errors.New("GetOffspringPolygenicDiseaseInfo_Fast called with genomeMap containing invalid locus value base: " + person1LocusBase2Value)
|
||||
}
|
||||
baseIsValid = slices.Contains(validAllelesList, person2LocusBase1Value)
|
||||
if (baseIsValid == false){
|
||||
return false, 0, 0, errors.New("GetOffspringPolygenicDiseaseInfo_Fast called with genomeMap containing invalid locus value base: " + person2LocusBase1Value)
|
||||
}
|
||||
baseIsValid = slices.Contains(validAllelesList, person2LocusBase2Value)
|
||||
if (baseIsValid == false){
|
||||
return false, 0, 0, errors.New("GetOffspringPolygenicDiseaseInfo_Fast called with genomeMap containing invalid locus value base: " + person2LocusBase2Value)
|
||||
}
|
||||
|
||||
numberOfLociTested += 1
|
||||
|
||||
offspringBasePairOutcome1 := person1LocusBase1Value + ";" + person2LocusBase1Value
|
||||
offspringBasePairOutcome2 := person1LocusBase2Value + ";" + person2LocusBase2Value
|
||||
offspringBasePairOutcome3 := person1LocusBase1Value + ";" + person2LocusBase2Value
|
||||
offspringBasePairOutcome4 := person1LocusBase2Value + ";" + person2LocusBase1Value
|
||||
|
||||
baseOutcomesList := []string{offspringBasePairOutcome1, offspringBasePairOutcome2, offspringBasePairOutcome3, offspringBasePairOutcome4}
|
||||
|
||||
outcomesSummedRiskWeight := 0
|
||||
|
||||
for _, outcomeBasePair := range baseOutcomesList{
|
||||
|
||||
offspringOutcomeRiskWeight, exists := locusRiskWeightsMap[outcomeBasePair]
|
||||
if (exists == false){
|
||||
// We do not know the risk weight for this base pair
|
||||
// We treat this as a 0 risk weight
|
||||
continue
|
||||
}
|
||||
|
||||
outcomesSummedRiskWeight += offspringOutcomeRiskWeight
|
||||
}
|
||||
|
||||
locusAverageRiskWeight := outcomesSummedRiskWeight/4
|
||||
|
||||
offspringSummedRiskWeights += locusAverageRiskWeight
|
||||
|
||||
offspringMinimumPossibleRiskWeightSum += locusMinimumWeight
|
||||
offspringMaximumPossibleRiskWeightSum += locusMaximumWeight
|
||||
}
|
||||
|
||||
offspringAverageDiseaseRiskScore, err := helpers.ScaleIntProportionally(true, offspringSummedRiskWeights, offspringMinimumPossibleRiskWeightSum, offspringMaximumPossibleRiskWeightSum, 0, 10)
|
||||
if (err != nil) { return false, 0, 0, err }
|
||||
|
||||
if (numberOfLociTested == 0){
|
||||
// No locations were tested
|
||||
return false, 0, 0, nil
|
||||
}
|
||||
|
||||
return true, offspringAverageDiseaseRiskScore, numberOfLociTested, nil
|
||||
}
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -bool: Any loci tested (if false, no offspring polygenic disease information is known)
|
||||
// -int: Offspring Risk Score (Value between 0-10)
|
||||
// -int: Number of loci tested
|
||||
// -map[[3]byte]geneticAnalysis.OffspringPolygenicDiseaseLocusInfo: Offspring Locus information map
|
||||
// Map Structure: Locus identifier -> OffspringPolygenicDiseaseLocusInfo
|
||||
// -bool: A neural network exists for this trait
|
||||
// -bool: Any loci tested (if false, no offspring polygenic disease analysis is known)
|
||||
// -int: Offspring Average Risk Score (Value between 0-10)
|
||||
// -map[int]float64: Prediction accuracy ranges map
|
||||
// -Map Structure: Probability prediction is accurate (X) -> Distance from prediction that must be travelled in both directions to
|
||||
// create a range in which the true value will fall into, X% of the time
|
||||
// -[]int: Sample offspring risks scores list
|
||||
// -int: Quantity of loci known
|
||||
// -int: Quantity of parental phased loci
|
||||
// -error
|
||||
func GetOffspringPolygenicDiseaseInfo(diseaseLociList []polygenicDiseases.DiseaseLocus, person1LocusValuesMap map[int64]locusValue.LocusValue, person2LocusValuesMap map[int64]locusValue.LocusValue)(bool, int, int, map[[3]byte]geneticAnalysis.OffspringPolygenicDiseaseLocusInfo, []int, error){
|
||||
func GetOffspringPolygenicDiseaseAnalysis(diseaseObject polygenicDiseases.PolygenicDisease, person1LocusValuesMap map[int64]locusValue.LocusValue, person2LocusValuesMap map[int64]locusValue.LocusValue)(bool, bool, int, map[int]float64, []int, int, int, error){
|
||||
|
||||
diseaseName := diseaseObject.DiseaseName
|
||||
|
||||
modelExists, _ := geneticPredictionModels.GetGeneticPredictionModelBytes(diseaseName)
|
||||
if (modelExists == false){
|
||||
// Prediction is not possible for this trait
|
||||
return false, false, 0, nil, nil, 0, 0, nil
|
||||
}
|
||||
|
||||
if (len(person1LocusValuesMap) == 0){
|
||||
return false, 0, 0, nil, nil, nil
|
||||
return true, false, 0, nil, nil, 0, 0, nil
|
||||
}
|
||||
if (len(person2LocusValuesMap) == 0){
|
||||
return false, 0, 0, nil, nil, nil
|
||||
return true, false, 0, nil, nil, 0, 0, nil
|
||||
}
|
||||
|
||||
// First, we create 100 prospective offspring genomes.
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
|
||||
diseaseLociRSIDsList := make([]int64, 0)
|
||||
// First we count up the quantity of parental phased loci
|
||||
// We only count the quantity of phased loci for loci which are known for both parents
|
||||
|
||||
for _, diseaseLocusObject := range diseaseLociList{
|
||||
quantityOfParentalPhasedLoci := 0
|
||||
|
||||
locusRSID := diseaseLocusObject.LocusRSID
|
||||
diseaseLociRSIDsList = append(diseaseLociRSIDsList, locusRSID)
|
||||
}
|
||||
for _, rsID := range diseaseLociList{
|
||||
|
||||
anyLocusValueExists, prospectiveOffspringGenomesList, err := getProspectiveOffspringGenomesList(diseaseLociRSIDsList, person1LocusValuesMap, person2LocusValuesMap)
|
||||
if (err != nil) { return false, 0, 0, nil, nil, err }
|
||||
if (anyLocusValueExists == false){
|
||||
return false, 0, 0, nil, nil, nil
|
||||
}
|
||||
|
||||
// This will sum every offspring's average disease risk score
|
||||
offspringAverageRiskScoreSum := 0
|
||||
|
||||
// This stores a list of every prospective offspring's risk score
|
||||
sampleOffspringRiskScoresList := make([]int, 0)
|
||||
|
||||
type offspringSummedLocusInfoObject struct{
|
||||
|
||||
SummedLocusRiskWeights int
|
||||
|
||||
SummedOddsRatios float64
|
||||
|
||||
NumberOfSummedOddsRatios int
|
||||
|
||||
// This is the number of unknown-odds-ratio-weight sums that we summed up
|
||||
NumberOfUnknownOddsRatioWeightSums int
|
||||
|
||||
// This is the sum of every unknown-odds-ratio-weight-sum for each prospective offspring for this genome
|
||||
UnknownOddsRatioWeightSumsSummed int
|
||||
}
|
||||
|
||||
// Map Structure: Locus Identifier -> offspringSummedLocusInfoObject
|
||||
offspringLocusInfoSumsMap := make(map[[3]byte]offspringSummedLocusInfoObject)
|
||||
|
||||
for offspringIndex, offspringGenomeMap := range prospectiveOffspringGenomesList{
|
||||
|
||||
offspringSummedRiskWeights := 0
|
||||
offspringMinimumPossibleRiskWeightSum := 0
|
||||
offspringMaximumPossibleRiskWeightSum := 0
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
locusIdentifierHex := locusObject.LocusIdentifier
|
||||
|
||||
locusIdentifier, err := encoding.DecodeHexStringTo3ByteArray(locusIdentifierHex)
|
||||
if (err != nil) { return false, 0, 0, nil, nil, err }
|
||||
|
||||
offspringLocusInfoSumsObject, exists := offspringLocusInfoSumsMap[locusIdentifier]
|
||||
person1LocusValue, exists := person1LocusValuesMap[rsID]
|
||||
if (exists == false){
|
||||
|
||||
if (offspringIndex != 0){
|
||||
// We already checked a previous offspring for this locus, and it's value doesn't exist
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
locusRiskWeightsMap := locusObject.RiskWeightsMap
|
||||
locusOddsRatiosMap := locusObject.OddsRatiosMap
|
||||
locusMinimumWeight := locusObject.MinimumRiskWeight
|
||||
locusMaximumWeight := locusObject.MaximumRiskWeight
|
||||
|
||||
basePairValueFound, locusBase1Value, locusBase2Value, _, _, err := createPersonGeneticAnalysis.GetLocusValueFromGenomeMap(true, offspringGenomeMap, locusRSID)
|
||||
if (err != nil) { return false, 0, 0, nil, nil, err }
|
||||
if (basePairValueFound == false){
|
||||
// None of the offspring will have a value for this locus
|
||||
continue
|
||||
}
|
||||
|
||||
locusRiskWeight, locusOddsRatioIsKnown, locusOddsRatio, err := createPersonGeneticAnalysis.GetGenomePolygenicDiseaseLocusRiskInfo(locusRiskWeightsMap, locusOddsRatiosMap, locusBase1Value, locusBase2Value)
|
||||
if (err != nil) { return false, 0, 0, nil, nil, err }
|
||||
|
||||
offspringLocusInfoSumsObject.SummedLocusRiskWeights += locusRiskWeight
|
||||
|
||||
if (locusOddsRatioIsKnown == true){
|
||||
offspringLocusInfoSumsObject.SummedOddsRatios += locusOddsRatio
|
||||
offspringLocusInfoSumsObject.NumberOfSummedOddsRatios += 1
|
||||
} else {
|
||||
offspringLocusInfoSumsObject.UnknownOddsRatioWeightSumsSummed += locusRiskWeight
|
||||
offspringLocusInfoSumsObject.NumberOfUnknownOddsRatioWeightSums += 1
|
||||
person2LocusValue, exists := person2LocusValuesMap[rsID]
|
||||
if (exists == false){
|
||||
continue
|
||||
}
|
||||
|
||||
offspringLocusInfoSumsMap[locusIdentifier] = offspringLocusInfoSumsObject
|
||||
|
||||
offspringSummedRiskWeights += locusRiskWeight
|
||||
|
||||
offspringMinimumPossibleRiskWeightSum += locusMinimumWeight
|
||||
offspringMaximumPossibleRiskWeightSum += locusMaximumWeight
|
||||
person1LocusIsPhased := person1LocusValue.LocusIsPhased
|
||||
if (person1LocusIsPhased == true){
|
||||
quantityOfParentalPhasedLoci += 1
|
||||
}
|
||||
|
||||
offspringAverageDiseaseRiskScore, err := helpers.ScaleIntProportionally(true, offspringSummedRiskWeights, offspringMinimumPossibleRiskWeightSum, offspringMaximumPossibleRiskWeightSum, 0, 10)
|
||||
if (err != nil) { return false, 0, 0, nil, nil, err }
|
||||
|
||||
sampleOffspringRiskScoresList = append(sampleOffspringRiskScoresList, offspringAverageDiseaseRiskScore)
|
||||
|
||||
offspringAverageRiskScoreSum += offspringAverageDiseaseRiskScore
|
||||
person2LocusIsPhased := person2LocusValue.LocusIsPhased
|
||||
if (person2LocusIsPhased == true){
|
||||
quantityOfParentalPhasedLoci += 1
|
||||
}
|
||||
}
|
||||
|
||||
numberOfLociTested := len(offspringLocusInfoSumsMap)
|
||||
// We create 100 prospective offspring genomes.
|
||||
|
||||
if (numberOfLociTested == 0){
|
||||
// No locations were tested
|
||||
return false, 0, 0, nil, nil, nil
|
||||
anyLocusValueExists, prospectiveOffspringGenomesList, err := getProspectiveOffspringGenomesList(diseaseLociList, person1LocusValuesMap, person2LocusValuesMap)
|
||||
if (err != nil) { return false, false, 0, nil, nil, 0, 0, err }
|
||||
if (anyLocusValueExists == false){
|
||||
return true, false, 0, nil, nil, 0, 0, nil
|
||||
}
|
||||
|
||||
offspringAverageRiskScore := offspringAverageRiskScoreSum/100
|
||||
// A list of predicted risk scores for each offspring
|
||||
predictedRiskScoresList := make([]int, 0)
|
||||
|
||||
// Map Structure: Locus Identifier -> OffspringPolygenicDiseaseLocusInfo
|
||||
offspringDiseaseLociInfoMap := make(map[[3]byte]geneticAnalysis.OffspringPolygenicDiseaseLocusInfo)
|
||||
accuracyRangesMap := make(map[int]float64)
|
||||
quantityOfLociTested := 0
|
||||
|
||||
for locusIdentifier, summedLocusInfoObject := range offspringLocusInfoSumsMap{
|
||||
for index, offspringGenomeMap := range prospectiveOffspringGenomesList{
|
||||
|
||||
summedLocusRiskWeights := summedLocusInfoObject.SummedLocusRiskWeights
|
||||
summedOddsRatios := summedLocusInfoObject.SummedOddsRatios
|
||||
numberOfSummedOddsRatios := summedLocusInfoObject.NumberOfSummedOddsRatios
|
||||
numberOfUnknownOddsRatioWeightSums := summedLocusInfoObject.NumberOfUnknownOddsRatioWeightSums
|
||||
unknownOddsRatioWeightSumsSummed := summedLocusInfoObject.UnknownOddsRatioWeightSumsSummed
|
||||
|
||||
// There are 100 prospective offspring, so we divide by 100
|
||||
locusAverageRiskWeight := summedLocusRiskWeights/100
|
||||
|
||||
newLocusInfoObject := geneticAnalysis.OffspringPolygenicDiseaseLocusInfo{
|
||||
OffspringAverageRiskWeight: locusAverageRiskWeight,
|
||||
neuralNetworkExists, predictionIsKnown, predictedRiskScore, predictionAccuracyRangesMap, currentQuantityOfLociTested, _, err := createPersonGeneticAnalysis.GetPersonGenomePolygenicDiseaseAnalysis(diseaseObject, offspringGenomeMap, false)
|
||||
if (err != nil){ return false, false, 0, nil, nil, 0, 0, err }
|
||||
if (neuralNetworkExists == false){
|
||||
return false, false, 0, nil, nil, 0, 0, errors.New("GetGenomeNumericTraitAnalysis claiming that neural network doesn't exist when we already checked.")
|
||||
}
|
||||
if (predictionIsKnown == false){
|
||||
return false, false, 0, nil, nil, 0, 0, errors.New("GetGenomeNumericTraitAnalysis claiming that prediction is impossible when we already know at least 1 locus value exists for trait.")
|
||||
}
|
||||
|
||||
if (numberOfSummedOddsRatios != 0){
|
||||
newLocusInfoObject.OffspringOddsRatioIsKnown = true
|
||||
predictedRiskScoresList = append(predictedRiskScoresList, predictedRiskScore)
|
||||
|
||||
offspringAverageOddsRatio := summedOddsRatios/float64(numberOfSummedOddsRatios)
|
||||
|
||||
newLocusInfoObject.OffspringAverageOddsRatio = offspringAverageOddsRatio
|
||||
if (index == 0){
|
||||
// These values should be the same for each predicted offspring
|
||||
accuracyRangesMap = predictionAccuracyRangesMap
|
||||
quantityOfLociTested = currentQuantityOfLociTested
|
||||
}
|
||||
}
|
||||
|
||||
if (numberOfUnknownOddsRatioWeightSums != 0){
|
||||
// We calculate the average predicted risk score
|
||||
|
||||
offspringAverageUnknownOddsRatiosWeightSum := unknownOddsRatioWeightSumsSummed/numberOfUnknownOddsRatioWeightSums
|
||||
outcomesSum := 0
|
||||
|
||||
newLocusInfoObject.OffspringAverageUnknownOddsRatiosWeightSum = offspringAverageUnknownOddsRatiosWeightSum
|
||||
for _, predictedRiskScore := range predictedRiskScoresList{
|
||||
outcomesSum += predictedRiskScore
|
||||
}
|
||||
|
||||
offspringDiseaseLociInfoMap[locusIdentifier] = newLocusInfoObject
|
||||
}
|
||||
averageRiskScore := outcomesSum/100
|
||||
|
||||
return true, offspringAverageRiskScore, numberOfLociTested, offspringDiseaseLociInfoMap, sampleOffspringRiskScoresList, nil
|
||||
return true, true, averageRiskScore, accuracyRangesMap, predictedRiskScoresList, quantityOfLociTested, quantityOfParentalPhasedLoci, nil
|
||||
}
|
||||
|
||||
|
||||
|
@ -1245,13 +1074,13 @@ func GetOffspringPolygenicDiseaseInfo(diseaseLociList []polygenicDiseases.Diseas
|
|||
// -int: Quantity of loci tested
|
||||
// -int: Quantity of parental phased loci
|
||||
// -error
|
||||
func GetOffspringDiscreteTraitInfo_NeuralNetwork(traitObject traits.Trait, person1LocusValuesMap map[int64]locusValue.LocusValue, person2LocusValuesMap map[int64]locusValue.LocusValue)(bool, bool, map[string]int, int, int, int, error){
|
||||
func GetOffspringDiscreteTraitAnalysis_NeuralNetwork(traitObject traits.Trait, person1LocusValuesMap map[int64]locusValue.LocusValue, person2LocusValuesMap map[int64]locusValue.LocusValue)(bool, bool, map[string]int, int, int, int, error){
|
||||
|
||||
traitName := traitObject.TraitName
|
||||
|
||||
traitIsDiscreteOrNumeric := traitObject.DiscreteOrNumeric
|
||||
if (traitIsDiscreteOrNumeric != "Discrete"){
|
||||
return false, false, nil, 0, 0, 0, errors.New("GetOffspringDiscreteTraitInfo_NeuralNetwork called with non-discrete trait.")
|
||||
return false, false, nil, 0, 0, 0, errors.New("GetOffspringDiscreteTraitAnalysis_NeuralNetwork called with non-discrete trait.")
|
||||
}
|
||||
|
||||
modelExists, _ := geneticPredictionModels.GetGeneticPredictionModelBytes(traitName)
|
||||
|
@ -1343,7 +1172,7 @@ func GetOffspringDiscreteTraitInfo_NeuralNetwork(traitObject traits.Trait, perso
|
|||
// -map[string]int: Offspring outcome probabilities map
|
||||
// Map Structure: Outcome Name -> Offspring probability of outcome (0-100)
|
||||
// -error
|
||||
func GetOffspringDiscreteTraitInfo_Rules(traitObject traits.Trait, person1LocusValuesMap map[int64]locusValue.LocusValue, person2LocusValuesMap map[int64]locusValue.LocusValue)(bool, bool, int, int, map[[3]byte]int, map[string]int, error){
|
||||
func GetOffspringDiscreteTraitAnalysis_Rules(traitObject traits.Trait, person1LocusValuesMap map[int64]locusValue.LocusValue, person2LocusValuesMap map[int64]locusValue.LocusValue)(bool, bool, int, int, map[[3]byte]int, map[string]int, error){
|
||||
|
||||
traitRulesList := traitObject.RulesList
|
||||
|
||||
|
@ -1421,7 +1250,6 @@ func GetOffspringDiscreteTraitInfo_Rules(traitObject traits.Trait, person1LocusV
|
|||
}
|
||||
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -bool: A neural network exists for this trait
|
||||
// -bool: Analysis exists (at least 1 locus exists for this analysis from both people's genomes
|
||||
|
@ -1433,13 +1261,13 @@ func GetOffspringDiscreteTraitInfo_Rules(traitObject traits.Trait, person1LocusV
|
|||
// -int: Quantity of loci known
|
||||
// -int: Quantity of parental phased loci
|
||||
// -error
|
||||
func GetOffspringNumericTraitInfo(traitObject traits.Trait, person1LocusValuesMap map[int64]locusValue.LocusValue, person2LocusValuesMap map[int64]locusValue.LocusValue)(bool, bool, float64, map[int]float64, []float64, int, int, error){
|
||||
func GetOffspringNumericTraitAnalysis(traitObject traits.Trait, person1LocusValuesMap map[int64]locusValue.LocusValue, person2LocusValuesMap map[int64]locusValue.LocusValue)(bool, bool, float64, map[int]float64, []float64, int, int, error){
|
||||
|
||||
traitName := traitObject.TraitName
|
||||
|
||||
traitIsDiscreteOrNumeric := traitObject.DiscreteOrNumeric
|
||||
if (traitIsDiscreteOrNumeric != "Numeric"){
|
||||
return false, false, 0, nil, nil, 0, 0, errors.New("GetOffspringNumericTraitInfo called with non-numeric trait.")
|
||||
return false, false, 0, nil, nil, 0, 0, errors.New("GetOffspringNumericTraitAnalysis called with non-numeric trait.")
|
||||
}
|
||||
|
||||
modelExists, _ := geneticPredictionModels.GetGeneticPredictionModelBytes(traitName)
|
||||
|
|
|
@ -8,10 +8,6 @@ package createPersonGeneticAnalysis
|
|||
|
||||
// Disclaimer: I am a novice in the ways of genetics. This package could be flawed in numerous ways.
|
||||
|
||||
// TODO: We want to eventually use neural nets for both trait and polygenic disease analysis (see geneticPrediction.go)
|
||||
// These will be trained on a set of genomes and will output a probability analysis for each trait/disease
|
||||
// This is only possible once we get access to the necessary training data
|
||||
|
||||
// TODO: Add the ability to weight different genome files based on their reliability.
|
||||
// Some files are much more accurate because they record each location many times.
|
||||
|
||||
|
@ -667,80 +663,6 @@ func GetPersonMonogenicDiseaseAnalysis(inputGenomesWithMetadataList []prepareRaw
|
|||
return personMonogenicDiseaseInfoObject, nil
|
||||
}
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -bool: Any loci tested
|
||||
// -int: Person genome risk score (value between 0-10)
|
||||
// -int: Person Genome Number of loci tested
|
||||
// -map[[3]byte]geneticAnalysis.PersonGenomePolygenicDiseaseLocusInfo: Person disease locus info map
|
||||
// Map Structure: Locus Identifier -> PersonGenomePolygenicDiseaseLocusInfo
|
||||
// -error
|
||||
func GetPersonGenomePolygenicDiseaseInfo(diseaseLociList []polygenicDiseases.DiseaseLocus, personLocusValuesMap map[int64]locusValue.LocusValue, lookForLocusAliases bool)(bool, int, int, map[[3]byte]geneticAnalysis.PersonGenomePolygenicDiseaseLocusInfo, error){
|
||||
|
||||
if (len(personLocusValuesMap) == 0){
|
||||
return false, 0, 0, nil, nil
|
||||
}
|
||||
|
||||
// Map Structure: Locus Identifier -> PersonGenomePolygenicDiseaseLocusInfo
|
||||
genomeLociInfoMap := make(map[[3]byte]geneticAnalysis.PersonGenomePolygenicDiseaseLocusInfo)
|
||||
|
||||
summedDiseaseRiskWeight := 0
|
||||
|
||||
minimumPossibleRiskWeightSum := 0
|
||||
maximumPossibleRiskWeightSum := 0
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
locusRiskWeightsMap := locusObject.RiskWeightsMap
|
||||
locusOddsRatiosMap := locusObject.OddsRatiosMap
|
||||
locusMinimumWeight := locusObject.MinimumRiskWeight
|
||||
locusMaximumWeight := locusObject.MaximumRiskWeight
|
||||
|
||||
locusValueFound, locusBase1Value, locusBase2Value, _, _, err := GetLocusValueFromGenomeMap(lookForLocusAliases, personLocusValuesMap, locusRSID)
|
||||
if (err != nil) { return false, 0, 0, nil, err }
|
||||
if (locusValueFound == false){
|
||||
continue
|
||||
}
|
||||
|
||||
locusRiskWeight, locusOddsRatioIsKnown, locusOddsRatio, err := GetGenomePolygenicDiseaseLocusRiskInfo(locusRiskWeightsMap, locusOddsRatiosMap, locusBase1Value, locusBase2Value)
|
||||
if (err != nil) { return false, 0, 0, nil, err }
|
||||
|
||||
newLocusInfoObject := geneticAnalysis.PersonGenomePolygenicDiseaseLocusInfo{
|
||||
RiskWeight: locusRiskWeight,
|
||||
OddsRatioIsKnown: locusOddsRatioIsKnown,
|
||||
}
|
||||
|
||||
if (locusOddsRatioIsKnown == true){
|
||||
newLocusInfoObject.OddsRatio = locusOddsRatio
|
||||
}
|
||||
|
||||
locusIdentifierHex := locusObject.LocusIdentifier
|
||||
|
||||
locusIdentifier, err := encoding.DecodeHexStringTo3ByteArray(locusIdentifierHex)
|
||||
if (err != nil) { return false, 0, 0, nil, err }
|
||||
|
||||
genomeLociInfoMap[locusIdentifier] = newLocusInfoObject
|
||||
|
||||
minimumPossibleRiskWeightSum += locusMinimumWeight
|
||||
maximumPossibleRiskWeightSum += locusMaximumWeight
|
||||
|
||||
summedDiseaseRiskWeight += locusRiskWeight
|
||||
}
|
||||
|
||||
numberOfLociTested := len(genomeLociInfoMap)
|
||||
if (numberOfLociTested == 0){
|
||||
// We have no information about this disease for this genome
|
||||
return false, 0, 0, nil, nil
|
||||
}
|
||||
|
||||
diseaseRiskScore, err := helpers.ScaleIntProportionally(true, summedDiseaseRiskWeight, minimumPossibleRiskWeightSum, maximumPossibleRiskWeightSum, 0, 10)
|
||||
if (err != nil) { return false, 0, 0, nil, err }
|
||||
|
||||
return true, diseaseRiskScore, numberOfLociTested, genomeLociInfoMap, nil
|
||||
}
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -geneticAnalysis.PersonPolygenicDiseaseInfo
|
||||
// -error
|
||||
|
@ -749,8 +671,6 @@ func GetPersonPolygenicDiseaseAnalysis(inputGenomesWithMetadataList []prepareRaw
|
|||
// We use this when returning errors
|
||||
emptyDiseaseInfoObject := geneticAnalysis.PersonPolygenicDiseaseInfo{}
|
||||
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
|
||||
// This map stores the polygenic disease for each of the person's genomes
|
||||
// Map Structure: Genome Identifier -> PersonGenomePolygenicDiseaseInfo
|
||||
personPolygenicDiseaseInfoMap := make(map[[16]byte]geneticAnalysis.PersonGenomePolygenicDiseaseInfo)
|
||||
|
@ -762,33 +682,17 @@ func GetPersonPolygenicDiseaseAnalysis(inputGenomesWithMetadataList []prepareRaw
|
|||
genomeIdentifier := genomeWithMetadataObject.GenomeIdentifier
|
||||
genomeMap := genomeWithMetadataObject.GenomeMap
|
||||
|
||||
// This map stores the loci for this disease and does not contain loci which do not belong to this disease
|
||||
// Map Structure: rsID -> Locus Value
|
||||
genomeLocusValuesMap := make(map[int64]locusValue.LocusValue)
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
|
||||
locusValueFound, _, _, _, locusValueObject, err := GetLocusValueFromGenomeMap(true, genomeMap, locusRSID)
|
||||
neuralNetworkExists, anyLociTested, personDiseaseRiskScore, predictionAccuracyRangesMap, genomeQuantityOfLociKnown, genomeQuantityOfPhasedLoci, err := GetPersonGenomePolygenicDiseaseAnalysis(diseaseObject, genomeMap, true)
|
||||
if (err != nil) { return emptyDiseaseInfoObject, err }
|
||||
if (locusValueFound == false){
|
||||
continue
|
||||
}
|
||||
|
||||
genomeLocusValuesMap[locusRSID] = locusValueObject
|
||||
}
|
||||
|
||||
anyLociTested, personDiseaseRiskScore, genomeNumberOfLociTested, genomeLociInfoMap, err := GetPersonGenomePolygenicDiseaseInfo(diseaseLociList, genomeLocusValuesMap, true)
|
||||
if (err != nil) { return emptyDiseaseInfoObject, err }
|
||||
if (anyLociTested == false){
|
||||
if (neuralNetworkExists == false || anyLociTested == false){
|
||||
continue
|
||||
}
|
||||
|
||||
newDiseaseInfoObject := geneticAnalysis.PersonGenomePolygenicDiseaseInfo{
|
||||
QuantityOfLociTested: genomeNumberOfLociTested,
|
||||
RiskScore: personDiseaseRiskScore,
|
||||
LociInfoMap: genomeLociInfoMap,
|
||||
ConfidenceRangesMap: predictionAccuracyRangesMap,
|
||||
QuantityOfLociKnown: genomeQuantityOfLociKnown,
|
||||
QuantityOfPhasedLoci: genomeQuantityOfPhasedLoci,
|
||||
}
|
||||
|
||||
personPolygenicDiseaseInfoMap[genomeIdentifier] = newDiseaseInfoObject
|
||||
|
@ -810,75 +714,20 @@ func GetPersonPolygenicDiseaseAnalysis(inputGenomesWithMetadataList []prepareRaw
|
|||
|
||||
// First we check to see if any of the genomes have different risk scores or NumberOfLociTested
|
||||
|
||||
genomeRiskScore := 0
|
||||
genomeNumberOfLociTested := 0
|
||||
personGenomePolygenicDiseaseInfoObject := geneticAnalysis.PersonGenomePolygenicDiseaseInfo{}
|
||||
|
||||
firstItemReached := false
|
||||
|
||||
for _, personGenomeDiseaseInfoObject := range personPolygenicDiseaseInfoMap{
|
||||
|
||||
currentGenomeRiskScore := personGenomeDiseaseInfoObject.RiskScore
|
||||
currentGenomeNumberOfLociTested := personGenomeDiseaseInfoObject.QuantityOfLociTested
|
||||
|
||||
if (firstItemReached == false){
|
||||
genomeRiskScore = currentGenomeRiskScore
|
||||
genomeNumberOfLociTested = currentGenomeNumberOfLociTested
|
||||
personGenomePolygenicDiseaseInfoObject = personGenomeDiseaseInfoObject
|
||||
firstItemReached = true
|
||||
continue
|
||||
}
|
||||
|
||||
if (genomeRiskScore != currentGenomeRiskScore){
|
||||
return true, nil
|
||||
}
|
||||
if (genomeNumberOfLociTested != currentGenomeNumberOfLociTested){
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Now we check for conflicts between the different locus values
|
||||
// We consider a conflict any time the same locus has different weights/odds ratios
|
||||
// We don't care if the loci have different base pair values, so long as those base pairs have the same risk weights/odds ratios
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
locusIdentifierHex := locusObject.LocusIdentifier
|
||||
|
||||
locusIdentifier, err := encoding.DecodeHexStringTo3ByteArray(locusIdentifierHex)
|
||||
if (err != nil) { return false, err }
|
||||
|
||||
locusRiskWeight := 0
|
||||
locusOddsRatio := float64(0)
|
||||
|
||||
firstItemReached := false
|
||||
|
||||
for _, personGenomeDiseaseInfoObject := range personPolygenicDiseaseInfoMap{
|
||||
|
||||
genomeLociInfoMap := personGenomeDiseaseInfoObject.LociInfoMap
|
||||
|
||||
genomeLocusObject, exists := genomeLociInfoMap[locusIdentifier]
|
||||
if (exists == false){
|
||||
if (firstItemReached == true){
|
||||
// A previous genome has information for this locus, and the current one does not
|
||||
return true, nil
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
genomeLocusRiskWeight := genomeLocusObject.RiskWeight
|
||||
genomeLocusOddsRatio := genomeLocusObject.OddsRatio
|
||||
|
||||
if (firstItemReached == false){
|
||||
locusRiskWeight = genomeLocusRiskWeight
|
||||
locusOddsRatio = genomeLocusOddsRatio
|
||||
firstItemReached = true
|
||||
continue
|
||||
}
|
||||
if (locusRiskWeight == genomeLocusRiskWeight && locusOddsRatio == genomeLocusOddsRatio){
|
||||
// No conflict exists for this locus on the genomes we have already checked
|
||||
continue
|
||||
}
|
||||
|
||||
// Conflict exists
|
||||
areEqual := reflect.DeepEqual(personGenomeDiseaseInfoObject, personGenomePolygenicDiseaseInfoObject)
|
||||
if (areEqual == false){
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
@ -895,6 +744,67 @@ func GetPersonPolygenicDiseaseAnalysis(inputGenomesWithMetadataList []prepareRaw
|
|||
}
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -bool: Neural network exists for disease
|
||||
// -bool: Any loci tested
|
||||
// -int: Person genome risk score (value between 0-10)
|
||||
// -map[int]float64: Confidence ranges map
|
||||
// -If we want to know how accurate the prediction is with a X% accuracy, how far would we have to expand the
|
||||
// risk score's range to be accurate, X% of the time?
|
||||
// -Map Structure: Percentage -> Distance to travel in both directions of prediction
|
||||
// -int: Person Genome quantity of loci known
|
||||
// -int: Person genome quantity of phased loci
|
||||
// -error
|
||||
func GetPersonGenomePolygenicDiseaseAnalysis(diseaseObject polygenicDiseases.PolygenicDisease, personGenomeMap map[int64]locusValue.LocusValue, checkForAliases bool)(bool, bool, int, map[int]float64, int, int, error){
|
||||
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
|
||||
getGenomeLocusValuesMap := func()(map[int64]locusValue.LocusValue, error){
|
||||
|
||||
if (checkForAliases == false){
|
||||
// We don't need to check for rsID aliases.
|
||||
return personGenomeMap, nil
|
||||
}
|
||||
|
||||
// This map contains the locus values for the genome
|
||||
// If a locus's entry doesn't exist, its value is unknown
|
||||
// Map Structure: Locus rsID -> Locus Value
|
||||
genomeLocusValuesMap := make(map[int64]locusValue.LocusValue)
|
||||
|
||||
for _, locusRSID := range diseaseLociList{
|
||||
|
||||
locusBasePairKnown, _, _, _, locusValueObject, err := GetLocusValueFromGenomeMap(checkForAliases, personGenomeMap, locusRSID)
|
||||
if (err != nil) { return nil, err }
|
||||
if (locusBasePairKnown == false){
|
||||
continue
|
||||
}
|
||||
|
||||
genomeLocusValuesMap[locusRSID] = locusValueObject
|
||||
}
|
||||
|
||||
return genomeLocusValuesMap, nil
|
||||
}
|
||||
|
||||
genomeLocusValuesMap, err := getGenomeLocusValuesMap()
|
||||
if (err != nil) { return false, false, 0, nil, 0, 0, err }
|
||||
|
||||
diseaseName := diseaseObject.DiseaseName
|
||||
|
||||
neuralNetworkModelExists, riskScorePredictionIsPossible, predictedRiskScore, predictionAccuracyRangesMap, quantityOfLociKnown, quantityOfPhasedLoci, err := geneticPrediction.GetNeuralNetworkNumericAttributePredictionFromGenomeMap(diseaseName, diseaseLociList, genomeLocusValuesMap)
|
||||
if (err != nil) { return false, false, 0, nil, 0, 0, err }
|
||||
if (neuralNetworkModelExists == false){
|
||||
return false, false, 0, nil, 0, 0, nil
|
||||
}
|
||||
if (riskScorePredictionIsPossible == false){
|
||||
return true, false, 0, nil, 0, 0, nil
|
||||
}
|
||||
|
||||
predictedRiskScoreInt := int(predictedRiskScore)
|
||||
|
||||
return true, true, predictedRiskScoreInt, predictionAccuracyRangesMap, quantityOfLociKnown, quantityOfPhasedLoci, nil
|
||||
}
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -geneticAnalysis.PersonDiscreteTraitInfo: Trait analysis object
|
||||
// -error
|
||||
|
@ -1073,35 +983,6 @@ func GetPersonNumericTraitAnalysis(inputGenomesWithMetadataList []prepareRawGeno
|
|||
return newPersonTraitInfoObject, nil
|
||||
}
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -int: Base pair disease locus risk weight
|
||||
// -bool: Base pair disease locus odds ratio known
|
||||
// -float64: Base pair disease locus odds ratio
|
||||
// -error
|
||||
func GetGenomePolygenicDiseaseLocusRiskInfo(locusRiskWeightsMap map[string]int, locusOddsRatiosMap map[string]float64, locusBase1Value string, locusBase2Value string)(int, bool, float64, error){
|
||||
|
||||
locusBasePairJoined := locusBase1Value + ";" + locusBase2Value
|
||||
|
||||
riskWeight, exists := locusRiskWeightsMap[locusBasePairJoined]
|
||||
if (exists == false){
|
||||
// This is an unknown base combination
|
||||
// We will treat it as a 0 risk weight
|
||||
return 0, true, 1, nil
|
||||
}
|
||||
|
||||
if (riskWeight == 0){
|
||||
return 0, true, 1, nil
|
||||
}
|
||||
|
||||
oddsRatio, exists := locusOddsRatiosMap[locusBasePairJoined]
|
||||
if (exists == false){
|
||||
return riskWeight, false, 0, nil
|
||||
}
|
||||
|
||||
return riskWeight, true, oddsRatio, nil
|
||||
}
|
||||
|
||||
// We use this to generate discrete trait predictions using a neural network
|
||||
// The alternative prediction method is to use Rules (see GetGenomeTraitAnalysis_Rules)
|
||||
//Outputs:
|
||||
|
@ -1357,6 +1238,8 @@ func GetGenomePassesDiscreteTraitRuleStatus(ruleLociList []traits.RuleLocus, gen
|
|||
// -error
|
||||
func GetGenomeNumericTraitAnalysis(traitObject traits.Trait, genomeMap map[int64]locusValue.LocusValue, checkForAliases bool)(bool, bool, float64, map[int]float64, int, int, error){
|
||||
|
||||
traitLociList := traitObject.LociList
|
||||
|
||||
getGenomeLocusValuesMap := func()(map[int64]locusValue.LocusValue, error){
|
||||
|
||||
if (checkForAliases == false){
|
||||
|
@ -1364,8 +1247,6 @@ func GetGenomeNumericTraitAnalysis(traitObject traits.Trait, genomeMap map[int64
|
|||
return genomeMap, nil
|
||||
}
|
||||
|
||||
traitLociList := traitObject.LociList
|
||||
|
||||
// This map contains the locus values for the genome
|
||||
// If a locus's entry doesn't exist, its value is unknown
|
||||
// Map Structure: Locus rsID -> Locus Value
|
||||
|
@ -1390,7 +1271,7 @@ func GetGenomeNumericTraitAnalysis(traitObject traits.Trait, genomeMap map[int64
|
|||
|
||||
traitName := traitObject.TraitName
|
||||
|
||||
neuralNetworkModelExists, traitPredictionIsPossible, predictedOutcome, predictionAccuracyRangesMap, quantityOfLociKnown, quantityOfPhasedLoci, err := geneticPrediction.GetNeuralNetworkNumericTraitPredictionFromGenomeMap(traitName, genomeLocusValuesMap)
|
||||
neuralNetworkModelExists, traitPredictionIsPossible, predictedOutcome, predictionAccuracyRangesMap, quantityOfLociKnown, quantityOfPhasedLoci, err := geneticPrediction.GetNeuralNetworkNumericAttributePredictionFromGenomeMap(traitName, traitLociList, genomeLocusValuesMap)
|
||||
if (err != nil) { return false, false, 0, nil, 0, 0, err }
|
||||
if (neuralNetworkModelExists == false){
|
||||
return false, false, 0, nil, 0, 0, nil
|
||||
|
|
|
@ -107,32 +107,21 @@ type PersonPolygenicDiseaseInfo struct{
|
|||
|
||||
type PersonGenomePolygenicDiseaseInfo struct{
|
||||
|
||||
// This describes the quantity of loci tested for this disease
|
||||
// This should be len(LociInfoMap)
|
||||
QuantityOfLociTested int
|
||||
|
||||
// This is total risk score for this disease for the person's genome
|
||||
// This is a number between 1-10
|
||||
RiskScore int
|
||||
|
||||
// This map contains info about all tested polygenic disease loci for this genome
|
||||
// If a locus does not exist in the map, its values are unknown
|
||||
// Map Structure: Locus Identifier -> PersonGenomePolygenicDiseaseLocusInfo
|
||||
LociInfoMap map[[3]byte]PersonGenomePolygenicDiseaseLocusInfo
|
||||
}
|
||||
// This map stores the confidence ranges for the predicted risk score
|
||||
// If we want to know how accurate the prediction is with a X% accuracy, how far would we have to expand the
|
||||
// risk score's range to be accurate, X% of the time?
|
||||
// For example: 50% accuracy requires a +/-2 point range, 80% accuracy requires a +-5 point range
|
||||
// Map Structure: Accuracy probability (0-100) -> Amount to add to value in both +/- directions so prediction is that accurate
|
||||
ConfidenceRangesMap map[int]float64
|
||||
|
||||
type PersonGenomePolygenicDiseaseLocusInfo struct{
|
||||
// This describes the quantity of loci tested for this disease
|
||||
QuantityOfLociKnown int
|
||||
|
||||
// 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
|
||||
|
||||
// This is valse if the odds ratio is not known
|
||||
OddsRatioIsKnown bool
|
||||
|
||||
// This is the person's genome odds ratio value for this variant's locus
|
||||
// A ratio >1 means their risk is increased, a ratio <1 means their risk is decreased
|
||||
OddsRatio float64
|
||||
QuantityOfPhasedLoci int
|
||||
}
|
||||
|
||||
|
||||
|
@ -325,7 +314,6 @@ type OffspringMonogenicDiseaseVariantInfo struct{
|
|||
ProbabilityOf2MutationsUpperBound int
|
||||
}
|
||||
|
||||
|
||||
type OffspringPolygenicDiseaseInfo struct{
|
||||
|
||||
// This map stores the polygenic disease info for each genome pair
|
||||
|
@ -339,16 +327,23 @@ type OffspringPolygenicDiseaseInfo struct{
|
|||
|
||||
type OffspringGenomePairPolygenicDiseaseInfo struct{
|
||||
|
||||
// This should be len(LociInfoMap)
|
||||
QuantityOfLociTested int
|
||||
|
||||
// A number between 1-10 representing the offspring's average risk score
|
||||
// 1 == lowest risk, 10 == highest risk
|
||||
OffspringAverageRiskScore int
|
||||
|
||||
// A map of the offspring's locus information
|
||||
// Map Structure: Locus Identifier -> OffspringPolygenicDiseaseLocusInfo
|
||||
LociInfoMap map[[3]byte]OffspringPolygenicDiseaseLocusInfo
|
||||
// This map stores the confidence ranges for the predicted risk score
|
||||
// If we want to know how accurate the prediction is with a X% accuracy, how far would we have to expand the
|
||||
// risk score's range to be accurate, X% of the time?
|
||||
// For example: 50% accuracy requires a +/-2 point range, 80% accuracy requires a +-3 point range
|
||||
// Map Structure: Accuracy probability (0-100) -> Amount to add to value in both +/- directions so prediction is that accurate
|
||||
PredictionConfidenceRangesMap map[int]float64
|
||||
|
||||
QuantityOfLociKnown int
|
||||
|
||||
// This describes the quantity of loci from both parents that are phased
|
||||
// For example, if there are 10 loci for this trait, and one parent has 10 phased loci and the other has 5,
|
||||
// this variable will have a value of 15
|
||||
QuantityOfParentalPhasedLoci int
|
||||
|
||||
// This is a list of prospective offspring risk scores
|
||||
// This is useful for plotting on a graph to understand the standard deviation of risk
|
||||
|
@ -356,27 +351,6 @@ type OffspringGenomePairPolygenicDiseaseInfo struct{
|
|||
}
|
||||
|
||||
|
||||
type OffspringPolygenicDiseaseLocusInfo struct{
|
||||
|
||||
// This is the offspring's average risk weight for this locus value
|
||||
// A higher weight means a higher risk of the disease
|
||||
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
|
||||
OffspringAverageOddsRatio float64
|
||||
|
||||
// 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
|
||||
OffspringAverageUnknownOddsRatiosWeightSum int
|
||||
}
|
||||
|
||||
|
||||
type OffspringDiscreteTraitInfo struct{
|
||||
|
||||
// This map stores the trait info for each genome pair
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// geneticPrediction provides functions to train and query neural network models
|
||||
// These models are currently used to predict traits such as eye color from user genome files
|
||||
// These models are used to predict attributes such as eye color and autism from user genome files
|
||||
|
||||
package geneticPrediction
|
||||
|
||||
|
@ -10,6 +10,7 @@ package geneticPrediction
|
|||
// Sorting matches by offspring total polygenic disease score will require inference on dozens of models for each match
|
||||
// We could create slower models that provide more accurate predictions
|
||||
|
||||
import "seekia/resources/geneticReferences/polygenicDiseases"
|
||||
import "seekia/resources/geneticReferences/traits"
|
||||
import "seekia/resources/geneticPredictionModels"
|
||||
|
||||
|
@ -48,7 +49,7 @@ type NeuralNetwork struct{
|
|||
// and the OutputLayer is a column representing their phenotype, such as eye color
|
||||
type TrainingData struct{
|
||||
|
||||
// InputLayer stores relevant rsID values for each trait from the user's genomes
|
||||
// InputLayer stores relevant rsID values for each attribute from the user's genomes
|
||||
// It also stores if each rsID is phased and if each rsID exists
|
||||
InputLayer []float32
|
||||
|
||||
|
@ -282,9 +283,9 @@ func DecodeBytesToDiscreteTraitPredictionAccuracyInfoMap(inputBytes []byte)(Disc
|
|||
return newDiscreteTraitPredictionAccuracyInfoMap, nil
|
||||
}
|
||||
|
||||
type NumericTraitPredictionAccuracyInfoMap map[NumericTraitPredictionInfo]NumericTraitPredictionAccuracyRangesMap
|
||||
type NumericAttributePredictionAccuracyInfoMap map[NumericAttributePredictionInfo]NumericAttributePredictionAccuracyRangesMap
|
||||
|
||||
type NumericTraitPredictionInfo struct{
|
||||
type NumericAttributePredictionInfo struct{
|
||||
|
||||
// This is a value between 0-100 which describes the percentage of the loci which were tested for the input for the prediction
|
||||
PercentageOfLociTested int
|
||||
|
@ -302,10 +303,10 @@ type NumericTraitPredictionInfo struct{
|
|||
// the true height value will fall into this range 90% of the time.
|
||||
// -50%+: 20 centimeters
|
||||
// -10%+: 10 centimeters
|
||||
type NumericTraitPredictionAccuracyRangesMap map[int]float64
|
||||
type NumericAttributePredictionAccuracyRangesMap map[int]float64
|
||||
|
||||
|
||||
func EncodeNumericTraitPredictionAccuracyInfoMapToBytes(inputMap NumericTraitPredictionAccuracyInfoMap)([]byte, error){
|
||||
func EncodeNumericAttributePredictionAccuracyInfoMapToBytes(inputMap NumericAttributePredictionAccuracyInfoMap)([]byte, error){
|
||||
|
||||
buffer := new(bytes.Buffer)
|
||||
|
||||
|
@ -319,22 +320,22 @@ func EncodeNumericTraitPredictionAccuracyInfoMapToBytes(inputMap NumericTraitPre
|
|||
return inputMapBytes, nil
|
||||
}
|
||||
|
||||
func DecodeBytesToNumericTraitPredictionAccuracyInfoMap(inputBytes []byte)(NumericTraitPredictionAccuracyInfoMap, error){
|
||||
func DecodeBytesToNumericAttributePredictionAccuracyInfoMap(inputBytes []byte)(NumericAttributePredictionAccuracyInfoMap, error){
|
||||
|
||||
if (inputBytes == nil){
|
||||
return nil, errors.New("DecodeBytesToNumericTraitPredictionAccuracyInfoMap called with nil inputBytes.")
|
||||
return nil, errors.New("DecodeBytesToNumericAttributePredictionAccuracyInfoMap called with nil inputBytes.")
|
||||
}
|
||||
|
||||
buffer := bytes.NewBuffer(inputBytes)
|
||||
|
||||
decoder := gob.NewDecoder(buffer)
|
||||
|
||||
var newNumericTraitPredictionAccuracyInfoMap NumericTraitPredictionAccuracyInfoMap
|
||||
var newNumericAttributePredictionAccuracyInfoMap NumericAttributePredictionAccuracyInfoMap
|
||||
|
||||
err := decoder.Decode(&newNumericTraitPredictionAccuracyInfoMap)
|
||||
err := decoder.Decode(&newNumericAttributePredictionAccuracyInfoMap)
|
||||
if (err != nil){ return nil, err }
|
||||
|
||||
return newNumericTraitPredictionAccuracyInfoMap, nil
|
||||
return newNumericAttributePredictionAccuracyInfoMap, nil
|
||||
}
|
||||
|
||||
//Outputs:
|
||||
|
@ -471,48 +472,37 @@ func GetNeuralNetworkDiscreteTraitPredictionFromGenomeMap(traitName string, geno
|
|||
return true, true, predictedOutcomeName, predictionAccuracy, quantityOfLociKnown, quantityOfPhasedLoci, nil
|
||||
}
|
||||
|
||||
// This function is used to predict numeric traits and polygenic disease risk scores
|
||||
//Outputs:
|
||||
// -bool: Neural network model exists for this trait (trait prediction is possible for this trait)
|
||||
// -bool: Trait prediction is possible for this user (User has at least 1 known trait locus value)
|
||||
// -float64: Predicted trait outcome (Example: Height in centimeters)
|
||||
// -bool: Neural network model exists for this attribute (neural network prediction is possible for this attribute)
|
||||
// -bool: Attribute prediction is possible for this user (User has at least 1 known attribute locus value)
|
||||
// -float64: Predicted attribute outcome (Example: Height in centimeters)
|
||||
// -map[int]float64: Accuracy ranges map
|
||||
// -Map Structure: Probability prediction is accurate (X) -> Distance from prediction that must be travelled in both directions to
|
||||
// create a range in which the true value will fall into, X% of the time
|
||||
// -int: Quantity of loci known
|
||||
// -int: Quantity of phased loci
|
||||
// -error
|
||||
func GetNeuralNetworkNumericTraitPredictionFromGenomeMap(traitName string, genomeMap map[int64]locusValue.LocusValue)(bool, bool, float64, map[int]float64, int, int, error){
|
||||
func GetNeuralNetworkNumericAttributePredictionFromGenomeMap(attributeName string, attributeLociList []int64, genomeMap map[int64]locusValue.LocusValue)(bool, bool, float64, map[int]float64, int, int, error){
|
||||
|
||||
traitObject, err := traits.GetTraitObject(traitName)
|
||||
if (err != nil) { return false, false, 0, nil, 0, 0, err }
|
||||
|
||||
traitIsDiscreteOrNumeric := traitObject.DiscreteOrNumeric
|
||||
if (traitIsDiscreteOrNumeric != "Numeric"){
|
||||
return false, false, 0, nil, 0, 0, errors.New("GetNeuralNetworkNumericTraitPredictionFromGenomeMap called with non-discrete trait: " + traitName)
|
||||
}
|
||||
|
||||
// This is a map of rsIDs which influence this trait
|
||||
traitRSIDsList := traitObject.LociList
|
||||
|
||||
if (len(traitRSIDsList) == 0){
|
||||
// Prediction is not possible for this trait
|
||||
return false, false, 0, nil, 0, 0, nil
|
||||
}
|
||||
|
||||
predictionModelExists, predictionModelBytes := geneticPredictionModels.GetGeneticPredictionModelBytes(traitName)
|
||||
predictionModelExists, predictionModelBytes := geneticPredictionModels.GetGeneticPredictionModelBytes(attributeName)
|
||||
if (predictionModelExists == false){
|
||||
// Prediction is not possible for this trait
|
||||
// Prediction is not possible for this attribute
|
||||
return false, false, 0, nil, 0, 0, nil
|
||||
}
|
||||
|
||||
traitRSIDsListCopy := slices.Clone(traitRSIDsList)
|
||||
slices.Sort(traitRSIDsListCopy)
|
||||
if (len(attributeLociList) == 0){
|
||||
return false, false, 0, nil, 0, 0, errors.New("GetNeuralNetworkNumericAttributePredictionFromGenomeMap called with empty attributeLociList for attribute with an existing neural network.")
|
||||
}
|
||||
|
||||
neuralNetworkInput, quantityOfLociKnown, quantityOfPhasedLoci, err := createInputNeuralNetworkLayerFromGenomeMap(traitRSIDsListCopy, genomeMap)
|
||||
attributeLociListCopy := slices.Clone(attributeLociList)
|
||||
slices.Sort(attributeLociListCopy)
|
||||
|
||||
neuralNetworkInput, quantityOfLociKnown, quantityOfPhasedLoci, err := createInputNeuralNetworkLayerFromGenomeMap(attributeLociListCopy, genomeMap)
|
||||
if (err != nil) { return false, false, 0, nil, 0, 0, err }
|
||||
|
||||
if (quantityOfLociKnown == 0){
|
||||
// We can't predict anything about this trait for this genome
|
||||
// We can't predict anything about this attribute for this genome
|
||||
return true, false, 0, nil, 0, 0, nil
|
||||
}
|
||||
|
||||
|
@ -522,25 +512,25 @@ func GetNeuralNetworkNumericTraitPredictionFromGenomeMap(traitName string, genom
|
|||
outputLayer, err := GetNeuralNetworkRawPrediction(&neuralNetworkObject, true, neuralNetworkInput)
|
||||
if (err != nil) { return false, false, 0, nil, 0, 0, err }
|
||||
|
||||
predictedOutcomeValue, err := GetNumericOutcomeValueFromOutputLayer(traitName, outputLayer)
|
||||
predictedOutcomeValue, err := GetNumericOutcomeValueFromOutputLayer(attributeName, outputLayer)
|
||||
if (err != nil) { return false, false, 0, nil, 0, 0, err }
|
||||
|
||||
modelTraitAccuracyInfoFile, err := geneticPredictionModels.GetPredictionModelNumericTraitAccuracyInfoBytes(traitName)
|
||||
modelAccuracyInfoFile, err := geneticPredictionModels.GetPredictionModelNumericAttributeAccuracyInfoBytes(attributeName)
|
||||
if (err != nil) { return false, false, 0, nil, 0, 0, err }
|
||||
|
||||
modelTraitAccuracyInfoMap, err := DecodeBytesToNumericTraitPredictionAccuracyInfoMap(modelTraitAccuracyInfoFile)
|
||||
modelAccuracyInfoMap, err := DecodeBytesToNumericAttributePredictionAccuracyInfoMap(modelAccuracyInfoFile)
|
||||
if (err != nil) { return false, false, 0, nil, 0, 0, err }
|
||||
|
||||
// We create a prediction confidence ranges map for our prediction
|
||||
|
||||
getPredictionConfidenceRangesMap := func()map[int]float64{
|
||||
|
||||
totalNumberOfTraitLoci := len(traitRSIDsList)
|
||||
totalNumberOfAttributeLoci := len(attributeLociListCopy)
|
||||
|
||||
proportionOfLociTested := float64(quantityOfLociKnown)/float64(totalNumberOfTraitLoci)
|
||||
proportionOfLociTested := float64(quantityOfLociKnown)/float64(totalNumberOfAttributeLoci)
|
||||
percentageOfLociTested := int(proportionOfLociTested * 100)
|
||||
|
||||
proportionOfPhasedLoci := float64(quantityOfPhasedLoci)/float64(totalNumberOfTraitLoci)
|
||||
proportionOfPhasedLoci := float64(quantityOfPhasedLoci)/float64(totalNumberOfAttributeLoci)
|
||||
percentageOfPhasedLoci := int(proportionOfPhasedLoci * 100)
|
||||
|
||||
// This is a value between 0 and 100 that represents the most similar confidence ranges map for this prediction
|
||||
|
@ -552,10 +542,10 @@ func GetNeuralNetworkNumericTraitPredictionFromGenomeMap(traitName string, genom
|
|||
// Y = Number of phased loci
|
||||
closestPredictionConfidenceRangesMapDistance := float64(0)
|
||||
|
||||
for traitOutcomeInfo, traitPredictionConfidenceRangesMap := range modelTraitAccuracyInfoMap{
|
||||
for attributeOutcomeInfo, attributePredictionConfidenceRangesMap := range modelAccuracyInfoMap{
|
||||
|
||||
currentPercentageOfLociTested := traitOutcomeInfo.PercentageOfLociTested
|
||||
currentPercentageOfPhasedLoci := traitOutcomeInfo.PercentageOfPhasedLoci
|
||||
currentPercentageOfLociTested := attributeOutcomeInfo.PercentageOfLociTested
|
||||
currentPercentageOfPhasedLoci := attributeOutcomeInfo.PercentageOfPhasedLoci
|
||||
|
||||
// Distance Formula for 2 coordinates (x1, y1) and (x2, y2):
|
||||
// distance = √((x2 - x1)^2 + (y2 - y1)^2)
|
||||
|
@ -567,12 +557,12 @@ func GetNeuralNetworkNumericTraitPredictionFromGenomeMap(traitName string, genom
|
|||
|
||||
if (distance == 0){
|
||||
// We found the exact prediction confidence ranges map
|
||||
return traitPredictionConfidenceRangesMap
|
||||
return attributePredictionConfidenceRangesMap
|
||||
}
|
||||
|
||||
if (closestPredictionConfidenceRangesMap == nil || distance < closestPredictionConfidenceRangesMapDistance){
|
||||
closestPredictionConfidenceRangesMapDistance = distance
|
||||
closestPredictionConfidenceRangesMap = traitPredictionConfidenceRangesMap
|
||||
closestPredictionConfidenceRangesMap = attributePredictionConfidenceRangesMap
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -789,11 +779,11 @@ func GetDiscreteOutcomeNameFromOutputLayer(traitName string, verifyOutputLayer b
|
|||
|
||||
|
||||
// This function returns which outcome is being described from a neural network's final output layer
|
||||
// This is only used for discrete traits
|
||||
// This is only used for numeric traits and polygenic diseases
|
||||
// Outputs:
|
||||
// -float64: Output Value (example: 150 centimeters)
|
||||
// -error
|
||||
func GetNumericOutcomeValueFromOutputLayer(traitName string, outputLayer []float32)(float64, error){
|
||||
func GetNumericOutcomeValueFromOutputLayer(attributeName string, outputLayer []float32)(float64, error){
|
||||
|
||||
if (len(outputLayer) != 1){
|
||||
return 0, errors.New("GetNumericOutcomeValueFromOutputLayer called with output layer which is not length of 1")
|
||||
|
@ -807,15 +797,19 @@ func GetNumericOutcomeValueFromOutputLayer(traitName string, outputLayer []float
|
|||
|
||||
getOutcomeMinAndMax := func()(float64, float64, error){
|
||||
|
||||
switch traitName{
|
||||
switch attributeName{
|
||||
case "Height":{
|
||||
// Shortest person of all time: 54 cm
|
||||
// Tallest person of all time: 272 cm
|
||||
return 54, 272, nil
|
||||
}
|
||||
case "Autism",
|
||||
"Homosexualness":{
|
||||
return 0, 10, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, 0, errors.New("GetNumericOutcomeValueFromOutputLayer called with unknown traitName: " + traitName)
|
||||
return 0, 0, errors.New("GetNumericOutcomeValueFromOutputLayer called with unknown attributeName: " + attributeName)
|
||||
}
|
||||
|
||||
outcomeMin, outcomeMax, err := getOutcomeMinAndMax()
|
||||
|
@ -833,9 +827,9 @@ func GetNumericOutcomeValueFromOutputLayer(traitName string, outputLayer []float
|
|||
// -int: Layer 3 neuron count
|
||||
// -int: Layer 4 neuron count (output layer)
|
||||
// -error
|
||||
func getNeuralNetworkLayerSizes(traitName string)(int, int, int, int, error){
|
||||
func getNeuralNetworkLayerSizes(attributeName string)(int, int, int, int, error){
|
||||
|
||||
switch traitName{
|
||||
switch attributeName{
|
||||
|
||||
case "Eye Color":{
|
||||
|
||||
|
@ -856,9 +850,19 @@ func getNeuralNetworkLayerSizes(traitName string)(int, int, int, int, error){
|
|||
// There is 1 output neuron, representing a height value
|
||||
return 3000, 3, 2, 1, nil
|
||||
}
|
||||
case "Autism":{
|
||||
// There are 1428 input neurons
|
||||
// There is 1 output neuron, representing an autism value
|
||||
return 1428, 3, 2, 1, nil
|
||||
}
|
||||
case "Homosexualness":{
|
||||
// There are 12 input neurons
|
||||
// There is 1 output neuron, representing a homosexualness value
|
||||
return 12, 10, 5, 1, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, 0, 0, 0, errors.New("getNeuralNetworkLayerSizes called with unknown traitName: " + traitName)
|
||||
return 0, 0, 0, 0, errors.New("getNeuralNetworkLayerSizes called with unknown attributeName: " + attributeName)
|
||||
}
|
||||
|
||||
//This function converts a genome allele to a neuron to use in a tensor
|
||||
|
@ -903,22 +907,50 @@ func convertAlleleToNeuron(allele string)(float32, error){
|
|||
// -[]TrainingData: List of TrainingData for the user which we will use to train the model
|
||||
// -error
|
||||
func CreateGeneticPredictionTrainingData_OpenSNP(
|
||||
traitName string,
|
||||
attributeName string,
|
||||
userPhenotypeDataObject readBiobankData.PhenotypeData_OpenSNP,
|
||||
userLocusValuesMap map[int64]locusValue.LocusValue)(bool, []TrainingData, error){
|
||||
|
||||
if (traitName != "Eye Color" && traitName != "Lactose Tolerance" && traitName != "Height"){
|
||||
return false, nil, errors.New("CreateGeneticPredictionTrainingData_OpenSNP called with unknown traitName: " + traitName)
|
||||
}
|
||||
//Outputs:
|
||||
// -[]int64: Attribute rsIDs list
|
||||
// -error
|
||||
getAttributeLociList := func()([]int64, error){
|
||||
|
||||
traitObject, err := traits.GetTraitObject(traitName)
|
||||
if (err != nil) { return false, nil, err }
|
||||
switch attributeName{
|
||||
|
||||
case "Eye Color",
|
||||
"Lactose Tolerance",
|
||||
"Height",
|
||||
"Homosexualness":{
|
||||
|
||||
traitObject, err := traits.GetTraitObject(attributeName)
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
// This is a list of rsIDs which influence this trait
|
||||
traitRSIDsList := traitObject.LociList
|
||||
traitLociList := traitObject.LociList
|
||||
|
||||
if (len(traitRSIDsList) == 0){
|
||||
return false, nil, errors.New("traitObject contains no rsIDs.")
|
||||
return traitLociList, nil
|
||||
}
|
||||
case "Autism":{
|
||||
|
||||
diseaseObject, err := polygenicDiseases.GetPolygenicDiseaseObject(attributeName)
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
// This is a list of rsIDs which influence this disease
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
|
||||
return diseaseLociList, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New("CreateGeneticPredictionTrainingData_OpenSNP called with unknown attributeName: " + attributeName)
|
||||
}
|
||||
|
||||
attributeLociList, err := getAttributeLociList()
|
||||
if (err != nil) { return false, nil, err }
|
||||
|
||||
if (len(attributeLociList) == 0){
|
||||
return false, nil, errors.New("getAttributeLociList returning empty attributeLociList.")
|
||||
}
|
||||
|
||||
// Each layer is represented as a []float32
|
||||
|
@ -927,7 +959,7 @@ func CreateGeneticPredictionTrainingData_OpenSNP(
|
|||
// Each TrainingData holds a variation of the user's genome rsID values
|
||||
// We add many rows with withheld data to improve training data
|
||||
|
||||
numberOfInputLayerRows, _, _, numberOfOutputLayerRows, err := getNeuralNetworkLayerSizes(traitName)
|
||||
numberOfInputLayerRows, _, _, numberOfOutputLayerRows, err := getNeuralNetworkLayerSizes(attributeName)
|
||||
if (err != nil) { return false, nil, err }
|
||||
|
||||
// Each rsID is represented by 3 neurons: LocusExists/LocusIsPhased, Allele1 Value, Allele2 Value
|
||||
|
@ -935,7 +967,7 @@ func CreateGeneticPredictionTrainingData_OpenSNP(
|
|||
// -0 = Locus value is unknown
|
||||
// -0.5 = Locus Is known, phase is unknown
|
||||
// -1 = Locus Is Known, phase is known
|
||||
expectedNumberOfInputLayerRows := len(traitRSIDsList) * 3
|
||||
expectedNumberOfInputLayerRows := len(attributeLociList) * 3
|
||||
|
||||
if (numberOfInputLayerRows != expectedNumberOfInputLayerRows){
|
||||
|
||||
|
@ -944,9 +976,9 @@ func CreateGeneticPredictionTrainingData_OpenSNP(
|
|||
return false, nil, errors.New("numberOfInputLayerRows is not expected: " + expectedNumberOfInputLayerRowsString)
|
||||
}
|
||||
|
||||
checkIfAnyTraitLocusValuesExist := func()bool{
|
||||
checkIfAnyAttributeLocusValuesExist := func()bool{
|
||||
|
||||
for _, rsID := range traitRSIDsList{
|
||||
for _, rsID := range attributeLociList{
|
||||
|
||||
_, exists := userLocusValuesMap[rsID]
|
||||
if (exists == true){
|
||||
|
@ -957,29 +989,29 @@ func CreateGeneticPredictionTrainingData_OpenSNP(
|
|||
return false
|
||||
}
|
||||
|
||||
anyTraitLocusValuesExist := checkIfAnyTraitLocusValuesExist()
|
||||
if (anyTraitLocusValuesExist == false){
|
||||
// The user's genome does not contain any of this trait's locus values
|
||||
anyAttributeLocusValuesExist := checkIfAnyAttributeLocusValuesExist()
|
||||
if (anyAttributeLocusValuesExist == false){
|
||||
// The user's genome does not contain any of this attribute's locus values
|
||||
// We will not train on their data
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
// We sort rsIDs in ascending order
|
||||
|
||||
traitRSIDsListCopy := slices.Clone(traitRSIDsList)
|
||||
slices.Sort(traitRSIDsListCopy)
|
||||
attributeLociListCopy := slices.Clone(attributeLociList)
|
||||
slices.Sort(attributeLociListCopy)
|
||||
|
||||
// This function returns the outputLayer for all trainingDatas for this user
|
||||
// Each outputLayer represents the user's trait value (Example: "Blue" for Eye Color)
|
||||
// Each outputLayer represents the user's attribute value (Example: "Blue" for Eye Color)
|
||||
// Each outputLayer is identical, because each TrainingData example belongs to the same user
|
||||
//
|
||||
// Outputs:
|
||||
// -bool: User trait value is known
|
||||
// -bool: User attribute value is known
|
||||
// -[]float32: Neuron values for layer
|
||||
// -error
|
||||
getUserTraitValueNeurons := func()(bool, []float32, error){
|
||||
getUserAttributeValueNeurons := func()(bool, []float32, error){
|
||||
|
||||
switch traitName{
|
||||
switch attributeName{
|
||||
|
||||
case "Eye Color":{
|
||||
|
||||
|
@ -1046,21 +1078,51 @@ func CreateGeneticPredictionTrainingData_OpenSNP(
|
|||
|
||||
return true, outputLayer, nil
|
||||
}
|
||||
}
|
||||
case "Autism":{
|
||||
|
||||
return false, nil, errors.New("Unknown traitName: " + traitName)
|
||||
}
|
||||
|
||||
userTraitValueExists, userTraitValueNeurons, err := getUserTraitValueNeurons()
|
||||
if (err != nil) { return false, nil, err }
|
||||
if (userTraitValueExists == false){
|
||||
// User cannot be used to train the model.
|
||||
// They do not have a value for this trait.
|
||||
userAutismIsKnown := userPhenotypeDataObject.AutismIsKnown
|
||||
if (userAutismIsKnown == false){
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
if (len(userTraitValueNeurons) != numberOfOutputLayerRows){
|
||||
return false, nil, errors.New("getUserTraitValueNeurons returning invalid length layer slice.")
|
||||
userAutism := userPhenotypeDataObject.Autism
|
||||
|
||||
outputValueFloat32 := float32(userAutism)
|
||||
|
||||
outputLayer := []float32{outputValueFloat32}
|
||||
|
||||
return true, outputLayer, nil
|
||||
}
|
||||
case "Homosexualness":{
|
||||
|
||||
userHomosexualnessIsKnown := userPhenotypeDataObject.HomosexualnessIsKnown
|
||||
if (userHomosexualnessIsKnown == false){
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
userHomosexualness := userPhenotypeDataObject.Homosexualness
|
||||
|
||||
outputValueFloat32 := float32(userHomosexualness)
|
||||
|
||||
outputLayer := []float32{outputValueFloat32}
|
||||
|
||||
return true, outputLayer, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil, errors.New("Unknown attributeName: " + attributeName)
|
||||
}
|
||||
|
||||
userAttributeValueExists, userAttributeValueNeurons, err := getUserAttributeValueNeurons()
|
||||
if (err != nil) { return false, nil, err }
|
||||
if (userAttributeValueExists == false){
|
||||
// User cannot be used to train the model.
|
||||
// They do not have a value for this attribute.
|
||||
return false, nil, nil
|
||||
}
|
||||
|
||||
if (len(userAttributeValueNeurons) != numberOfOutputLayerRows){
|
||||
return false, nil, errors.New("getUserAttributeValueNeurons returning invalid length layer slice.")
|
||||
}
|
||||
|
||||
// We want the initial training data to be the same for each call of this function that has the same input parameters
|
||||
|
@ -1134,11 +1196,11 @@ func CreateGeneticPredictionTrainingData_OpenSNP(
|
|||
|
||||
anyLocusExists := false
|
||||
|
||||
inputLayerLength := len(traitRSIDsListCopy) * 3
|
||||
inputLayerLength := len(attributeLociListCopy) * 3
|
||||
|
||||
inputLayer := make([]float32, 0, inputLayerLength)
|
||||
|
||||
for _, rsID := range traitRSIDsListCopy{
|
||||
for _, rsID := range attributeLociListCopy{
|
||||
|
||||
randomFloat := pseudorandomNumberGenerator.Float64()
|
||||
if (randomFloat > probabilityOfUsingLoci){
|
||||
|
@ -1209,11 +1271,11 @@ func CreateGeneticPredictionTrainingData_OpenSNP(
|
|||
continue
|
||||
}
|
||||
|
||||
userTraitValueNeuronsCopy := slices.Clone(userTraitValueNeurons)
|
||||
userAttributeValueNeuronsCopy := slices.Clone(userAttributeValueNeurons)
|
||||
|
||||
newTrainingData := TrainingData{
|
||||
InputLayer: inputLayer,
|
||||
OutputLayer: userTraitValueNeuronsCopy,
|
||||
OutputLayer: userAttributeValueNeuronsCopy,
|
||||
}
|
||||
|
||||
trainingDataList = append(trainingDataList, newTrainingData)
|
||||
|
@ -1222,9 +1284,9 @@ func CreateGeneticPredictionTrainingData_OpenSNP(
|
|||
return true, trainingDataList, nil
|
||||
}
|
||||
|
||||
func GetNewUntrainedNeuralNetworkObject(traitName string)(*NeuralNetwork, error){
|
||||
func GetNewUntrainedNeuralNetworkObject(attributeName string)(*NeuralNetwork, error){
|
||||
|
||||
layer1NeuronCount, layer2NeuronCount, layer3NeuronCount, layer4NeuronCount, err := getNeuralNetworkLayerSizes(traitName)
|
||||
layer1NeuronCount, layer2NeuronCount, layer3NeuronCount, layer4NeuronCount, err := getNeuralNetworkLayerSizes(attributeName)
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
// This is the graph object we add each layer to
|
||||
|
@ -1304,10 +1366,10 @@ func (inputNetwork *NeuralNetwork)getLearnables()gorgonia.Nodes{
|
|||
// This function will train the neural network
|
||||
// The function is passed a batch of TrainingData examples to train on
|
||||
// Inputs:
|
||||
// -string: Trait Name
|
||||
// -bool: Trait is Numeric
|
||||
// -An example of a numeric trait is Height
|
||||
// -An example of a discrete trait is Eye Color, which has discrete outcomes (colors)
|
||||
// -string: Attribute Name
|
||||
// -bool: Attribute is Numeric
|
||||
// -An example of a numeric attribute is Height
|
||||
// -An example of a discrete attribute is Eye Color, which has discrete outcomes (colors)
|
||||
// -*NeuralNetwork
|
||||
// -func()(bool, bool, TrainingData, error): Function to get the next training data.
|
||||
// -Outputs:
|
||||
|
@ -1318,9 +1380,9 @@ func (inputNetwork *NeuralNetwork)getLearnables()gorgonia.Nodes{
|
|||
// Outputs:
|
||||
// -bool: Process completed (was not stopped mid-way)
|
||||
// -error
|
||||
func TrainNeuralNetwork(traitName string, traitIsNumeric bool, neuralNetworkObject *NeuralNetwork, getNextTrainingData func()(bool, bool, TrainingData, error))(bool, error){
|
||||
func TrainNeuralNetwork(attributeName string, attributeIsNumeric bool, neuralNetworkObject *NeuralNetwork, getNextTrainingData func()(bool, bool, TrainingData, error))(bool, error){
|
||||
|
||||
layer1NeuronCount, _, _, layer4NeuronCount, err := getNeuralNetworkLayerSizes(traitName)
|
||||
layer1NeuronCount, _, _, layer4NeuronCount, err := getNeuralNetworkLayerSizes(attributeName)
|
||||
if (err != nil) { return false, err }
|
||||
|
||||
neuralNetworkGraph := neuralNetworkObject.graph
|
||||
|
@ -1340,7 +1402,7 @@ func TrainNeuralNetwork(traitName string, traitIsNumeric bool, neuralNetworkObje
|
|||
gorgonia.WithShape(1, layer4NeuronCount),
|
||||
)
|
||||
|
||||
err = neuralNetworkObject.buildNeuralNetwork(trainingDataInputNode, traitIsNumeric)
|
||||
err = neuralNetworkObject.buildNeuralNetwork(trainingDataInputNode, attributeIsNumeric)
|
||||
if (err != nil) { return false, err }
|
||||
|
||||
// This computes the loss (how accurate was our prediction)
|
||||
|
@ -1431,7 +1493,7 @@ func TrainNeuralNetwork(traitName string, traitIsNumeric bool, neuralNetworkObje
|
|||
// Outputs:
|
||||
// -[]float32: Output neurons
|
||||
// -error
|
||||
func GetNeuralNetworkRawPrediction(inputNeuralNetwork *NeuralNetwork, traitIsNumeric bool, inputLayer []float32)([]float32, error){
|
||||
func GetNeuralNetworkRawPrediction(inputNeuralNetwork *NeuralNetwork, attributeIsNumeric bool, inputLayer []float32)([]float32, error){
|
||||
|
||||
neuralNetworkGraph := inputNeuralNetwork.graph
|
||||
|
||||
|
@ -1455,7 +1517,7 @@ func GetNeuralNetworkRawPrediction(inputNeuralNetwork *NeuralNetwork, traitIsNum
|
|||
if (err != nil) { return nil, err }
|
||||
|
||||
|
||||
err = inputNeuralNetwork.buildNeuralNetwork(inputNode, traitIsNumeric)
|
||||
err = inputNeuralNetwork.buildNeuralNetwork(inputNode, attributeIsNumeric)
|
||||
if (err != nil){ return nil, err }
|
||||
|
||||
// Now we create a virtual machine to compute the prediction
|
||||
|
@ -1479,7 +1541,7 @@ func GetNeuralNetworkRawPrediction(inputNeuralNetwork *NeuralNetwork, traitIsNum
|
|||
|
||||
// This function will take a neural network and input layer and build the network to be able to compute a prediction
|
||||
// We need to run a virtual machine after calling this function in order for the prediction to be generated
|
||||
func (inputNetwork *NeuralNetwork)buildNeuralNetwork(inputLayer *gorgonia.Node, traitIsNumeric bool)error{
|
||||
func (inputNetwork *NeuralNetwork)buildNeuralNetwork(inputLayer *gorgonia.Node, predictionIsNumeric bool)error{
|
||||
|
||||
// We copy node pointer (says to do this in a resource i'm reading)
|
||||
|
||||
|
@ -1518,7 +1580,7 @@ func (inputNetwork *NeuralNetwork)buildNeuralNetwork(inputLayer *gorgonia.Node,
|
|||
return errors.New("Layer 3 multiplication failed: " + err.Error())
|
||||
}
|
||||
|
||||
if (traitIsNumeric == false){
|
||||
if (predictionIsNumeric == false){
|
||||
|
||||
// We SoftMax the output to get the prediction
|
||||
|
||||
|
|
|
@ -483,193 +483,74 @@ func GetOffspringMonogenicDiseaseVariantInfoFromGeneticAnalysis(coupleAnalysisOb
|
|||
return true, probabilityOf0MutationsLowerBound, probabilityOf0MutationsUpperBound, probabilityOf0MutationsFormatted, probabilityOf1MutationLowerBound, probabilityOf1MutationUpperBound, probabilityOf1MutationFormatted, probabilityOf2MutationsLowerBound, probabilityOf2MutationsUpperBound, probabilityOf2MutationsFormatted, nil
|
||||
}
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -bool: Polygenic Disease Risk Score known (any loci values exist)
|
||||
// -int: Person Disease risk score
|
||||
// -string: Person Disease risk score formatted (has "/10" suffix)
|
||||
// -int: Quantity of loci tested
|
||||
// -bool: Conflict exists
|
||||
// -bool: Any analysis exists
|
||||
// -int: Predicted risk score (0-10)
|
||||
// -map[int]float64: Prediction confidence ranges map
|
||||
// -Map Structure: Percentage probability of accurate prediction -> distance of range in both directions from prediction
|
||||
// -int: Quantity of loci known
|
||||
// -int: Quantity of phased loci
|
||||
// -bool: Conflict exists (between any of these results for each genome)
|
||||
// -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, map[int]float64, int, int, bool, error){
|
||||
|
||||
personPolygenicDiseasesMap := personAnalysisObject.PolygenicDiseasesMap
|
||||
|
||||
personPolygenicDiseaseInfo, exists := personPolygenicDiseasesMap[diseaseName]
|
||||
personDiseaseInfoObject, exists := personPolygenicDiseasesMap[diseaseName]
|
||||
if (exists == false){
|
||||
return false, 0, "", 0, false, nil
|
||||
return false, 0, nil, 0, 0, false, nil
|
||||
}
|
||||
|
||||
personPolygenicDiseaseInfoMap := personPolygenicDiseaseInfo.PolygenicDiseaseInfoMap
|
||||
personDiseaseInfoMap := personDiseaseInfoObject.PolygenicDiseaseInfoMap
|
||||
conflictExists := personDiseaseInfoObject.ConflictExists
|
||||
|
||||
genomePolygenicDiseaseInfo, exists := personPolygenicDiseaseInfoMap[genomeIdentifier]
|
||||
personGenomeDiseaseInfoObject, exists := personDiseaseInfoMap[genomeIdentifier]
|
||||
if (exists == false){
|
||||
return false, 0, "", 0, false, nil
|
||||
return false, 0, nil, 0, 0, false, nil
|
||||
}
|
||||
|
||||
conflictExists := personPolygenicDiseaseInfo.ConflictExists
|
||||
predictedRiskScore := personGenomeDiseaseInfoObject.RiskScore
|
||||
confidenceRangesMap := personGenomeDiseaseInfoObject.ConfidenceRangesMap
|
||||
quantityOfLociKnown := personGenomeDiseaseInfoObject.QuantityOfLociKnown
|
||||
quantityOfPhasedLoci := personGenomeDiseaseInfoObject.QuantityOfPhasedLoci
|
||||
|
||||
personDiseaseRiskScore := genomePolygenicDiseaseInfo.RiskScore
|
||||
|
||||
personDiseaseRiskScoreString := helpers.ConvertIntToString(personDiseaseRiskScore)
|
||||
|
||||
personDiseaseRiskScoreFormatted := personDiseaseRiskScoreString + "/10"
|
||||
|
||||
quantityOfLociTested := genomePolygenicDiseaseInfo.QuantityOfLociTested
|
||||
|
||||
return true, personDiseaseRiskScore, personDiseaseRiskScoreFormatted, quantityOfLociTested, conflictExists, nil
|
||||
return true, predictedRiskScore, confidenceRangesMap, quantityOfLociKnown, quantityOfPhasedLoci, conflictExists, nil
|
||||
}
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -bool: Offspring Disease Risk Score known
|
||||
// -int: Offspring average disease risk score
|
||||
// -string: Offspring Disease average risk score formatted (has "/10" suffix)
|
||||
// -[]int: Sample Offspring Risk Scores List
|
||||
// -int: Quantity of loci tested
|
||||
// -bool: Conflict exists
|
||||
// -bool: Analysis exists
|
||||
// -int: Average offspring risk score (0-10)
|
||||
// -map[int]float64: Prediction confidence ranges map
|
||||
// -int: Quantity of loci known
|
||||
// -int: Quantity of Parental phased loci
|
||||
// -[]int: 100 Sample offspring risk scores
|
||||
// -bool: Conflict exists (Between this genome pair and other genome pairs)
|
||||
// -error
|
||||
func GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, genomePairIdentifier [32]byte)(bool, int, string, []int, int, bool, error){
|
||||
func GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, genomePairIdentifier [32]byte)(bool, int, map[int]float64, int, int, []int, bool, error){
|
||||
|
||||
couplePolygenicDiseasesMap := coupleAnalysisObject.PolygenicDiseasesMap
|
||||
offspringDiseasesMap := coupleAnalysisObject.PolygenicDiseasesMap
|
||||
|
||||
couplePolygenicDiseaseInfo, exists := couplePolygenicDiseasesMap[diseaseName]
|
||||
diseaseInfoObject, exists := offspringDiseasesMap[diseaseName]
|
||||
if (exists == false){
|
||||
return false, 0, "", nil, 0, false, nil
|
||||
return false, 0, nil, 0, 0, nil, false, nil
|
||||
}
|
||||
|
||||
polygenicDiseaseInfoMap := couplePolygenicDiseaseInfo.PolygenicDiseaseInfoMap
|
||||
diseaseInfoMap := diseaseInfoObject.PolygenicDiseaseInfoMap
|
||||
conflictExists := diseaseInfoObject.ConflictExists
|
||||
|
||||
genomePairPolygenicDiseaseInfo, exists := polygenicDiseaseInfoMap[genomePairIdentifier]
|
||||
genomePairDiseaseInfoObject, exists := diseaseInfoMap[genomePairIdentifier]
|
||||
if (exists == false){
|
||||
return false, 0, "", nil, 0, false, nil
|
||||
return false, 0, nil, 0, 0, nil, false, nil
|
||||
}
|
||||
|
||||
conflictExists := couplePolygenicDiseaseInfo.ConflictExists
|
||||
offspringAverageRiskScore := genomePairDiseaseInfoObject.OffspringAverageRiskScore
|
||||
predictionConfidenceRangesMap := genomePairDiseaseInfoObject.PredictionConfidenceRangesMap
|
||||
quantityOfLociKnown := genomePairDiseaseInfoObject.QuantityOfLociKnown
|
||||
quantityOfParentalPhasedLoci := genomePairDiseaseInfoObject.QuantityOfParentalPhasedLoci
|
||||
sampleOffspringRiskScoresList := genomePairDiseaseInfoObject.SampleOffspringRiskScoresList
|
||||
|
||||
quantityOfLociTested := genomePairPolygenicDiseaseInfo.QuantityOfLociTested
|
||||
|
||||
offspringAverageRiskScore := genomePairPolygenicDiseaseInfo.OffspringAverageRiskScore
|
||||
|
||||
offspringAverageRiskScoreString := helpers.ConvertIntToString(offspringAverageRiskScore)
|
||||
|
||||
offspringAverageRiskScoreFormatted := offspringAverageRiskScoreString + "/10"
|
||||
|
||||
sampleOffspringRiskScoresList := genomePairPolygenicDiseaseInfo.SampleOffspringRiskScoresList
|
||||
|
||||
return true, offspringAverageRiskScore, offspringAverageRiskScoreFormatted, sampleOffspringRiskScoresList, quantityOfLociTested, conflictExists, nil
|
||||
}
|
||||
|
||||
//Outputs:
|
||||
// -bool: Risk Weight and base pair known
|
||||
// -int: Locus risk weight
|
||||
// -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, bool, float64, string, error){
|
||||
|
||||
personPolygenicDiseasesMap := personAnalyisObject.PolygenicDiseasesMap
|
||||
|
||||
personPolygenicDiseaseMap, exists := personPolygenicDiseasesMap[diseaseName]
|
||||
if (exists == false){
|
||||
return false, 0, false, 0, "", nil
|
||||
}
|
||||
|
||||
personPolygenicDiseaseInfoMap := personPolygenicDiseaseMap.PolygenicDiseaseInfoMap
|
||||
|
||||
personGenomePolygenicDiseaseInfo, exists := personPolygenicDiseaseInfoMap[genomeIdentifier]
|
||||
if (exists == false){
|
||||
return false, 0, false, 0, "", nil
|
||||
}
|
||||
|
||||
genomeLociInfoMap := personGenomePolygenicDiseaseInfo.LociInfoMap
|
||||
|
||||
locusInfoObject, exists := genomeLociInfoMap[locusIdentifier]
|
||||
if (exists == false){
|
||||
return false, 0, false, 0, "", nil
|
||||
}
|
||||
|
||||
locusRiskWeight := locusInfoObject.RiskWeight
|
||||
|
||||
locusOddsRatioIsKnown := locusInfoObject.OddsRatioIsKnown
|
||||
if (locusOddsRatioIsKnown == false){
|
||||
return true, locusRiskWeight, false, 0, "", nil
|
||||
}
|
||||
|
||||
locusOddsRatio := locusInfoObject.OddsRatio
|
||||
|
||||
genomeLocusOddsRatioString := helpers.ConvertFloat64ToStringRounded(locusOddsRatio, 2)
|
||||
|
||||
locusOddsRatioFormatted := genomeLocusOddsRatioString + "x"
|
||||
|
||||
return true, locusRiskWeight, true, locusOddsRatio, locusOddsRatioFormatted, nil
|
||||
}
|
||||
|
||||
//Outputs:
|
||||
// -bool: Offspring risk weight known
|
||||
// -int: Offspring risk weight
|
||||
// -bool: Offspring odds ratio known
|
||||
// -float64: Offspring odds ratio
|
||||
// -string: Offspring odds ratio formatted (with + and < from unknownFactors weight sum and x suffix)
|
||||
// -error
|
||||
func GetOffspringPolygenicDiseaseLocusInfoFromGeneticAnalysis(coupleAnalysisObject geneticAnalysis.CoupleAnalysis, diseaseName string, locusIdentifier [3]byte, genomePairIdentifier [32]byte)(bool, int, bool, float64, string, error){
|
||||
|
||||
offspringPolygenicDiseasesMap := coupleAnalysisObject.PolygenicDiseasesMap
|
||||
|
||||
offspringPolygenicDiseaseInfo, exists := offspringPolygenicDiseasesMap[diseaseName]
|
||||
if (exists == false){
|
||||
return false, 0, false, 0, "", nil
|
||||
}
|
||||
|
||||
offspringPolygenicDiseaseMap := offspringPolygenicDiseaseInfo.PolygenicDiseaseInfoMap
|
||||
|
||||
genomePairPolygenicDiseaseInfo, exists := offspringPolygenicDiseaseMap[genomePairIdentifier]
|
||||
if (exists == false){
|
||||
return false, 0, false, 0, "", nil
|
||||
}
|
||||
|
||||
genomePairLociInfoMap := genomePairPolygenicDiseaseInfo.LociInfoMap
|
||||
|
||||
locusInfoObject, exists := genomePairLociInfoMap[locusIdentifier]
|
||||
if (exists == false){
|
||||
return false, 0, false, 0, "", nil
|
||||
}
|
||||
|
||||
offspringAverageRiskWeight := locusInfoObject.OffspringAverageRiskWeight
|
||||
offspringOddsRatioIsKnown := locusInfoObject.OffspringOddsRatioIsKnown
|
||||
|
||||
if (offspringOddsRatioIsKnown == false){
|
||||
return true, offspringAverageRiskWeight, false, 0, "", nil
|
||||
}
|
||||
|
||||
offspringAverageOddsRatio := locusInfoObject.OffspringAverageOddsRatio
|
||||
|
||||
getOddsRatioFormatted := func()string{
|
||||
|
||||
offspringAverageUnknownOddsRatiosWeightSum := locusInfoObject.OffspringAverageUnknownOddsRatiosWeightSum
|
||||
|
||||
offspringAverageOddsRatioString := helpers.ConvertFloat64ToStringRounded(offspringAverageOddsRatio, 2)
|
||||
|
||||
if (offspringAverageUnknownOddsRatiosWeightSum == 0){
|
||||
result := offspringAverageOddsRatioString + "x"
|
||||
|
||||
return result
|
||||
}
|
||||
if (offspringAverageUnknownOddsRatiosWeightSum < 0){
|
||||
result := "<" + offspringAverageOddsRatioString + "x"
|
||||
|
||||
return result
|
||||
}
|
||||
// offspringAverageUnknownOddsRatiosWeightSum > 0
|
||||
result := offspringAverageOddsRatioString + "x+"
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
oddsRatioFormatted := getOddsRatioFormatted()
|
||||
|
||||
return true, offspringAverageRiskWeight, true, offspringAverageOddsRatio, oddsRatioFormatted, nil
|
||||
return true, offspringAverageRiskScore, predictionConfidenceRangesMap, quantityOfLociKnown, quantityOfParentalPhasedLoci, sampleOffspringRiskScoresList, conflictExists, nil
|
||||
}
|
||||
|
||||
//Outputs:
|
||||
|
@ -892,7 +773,6 @@ func GetOffspringDiscreteTraitRuleInfoFromGeneticAnalysis(coupleAnalysisObject g
|
|||
}
|
||||
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -bool: Any analysis exists
|
||||
// -float64: Predicted outcome (Example: Height in centimeters)
|
||||
|
@ -964,6 +844,8 @@ func GetOffspringNumericTraitInfoFromGeneticAnalysis(coupleAnalysisObject geneti
|
|||
return true, offspringAverageOutcome, predictionConfidenceRangesMap, quantityOfLociKnown, quantityOfParentalPhasedLoci, sampleOffspringOutcomesList, conflictExists, nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
// We use this function to verify a person genetic analysis is well formed
|
||||
//TODO: Perform sanity checks on data
|
||||
func VerifyPersonGeneticAnalysis(personAnalysisObject geneticAnalysis.PersonAnalysis)error{
|
||||
|
@ -1015,25 +897,9 @@ func VerifyPersonGeneticAnalysis(personAnalysisObject geneticAnalysis.PersonAnal
|
|||
|
||||
for _, genomeIdentifier := range allGenomeIdentifiersList{
|
||||
|
||||
_, _, _, _, _, err := GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(personAnalysisObject, diseaseName, genomeIdentifier)
|
||||
_, _, _, _, _, _, err := GetPersonPolygenicDiseaseInfoFromGeneticAnalysis(personAnalysisObject, diseaseName, genomeIdentifier)
|
||||
if (err != nil) { return err }
|
||||
}
|
||||
|
||||
diseaseLocusObjectsList := diseaseObject.LociList
|
||||
|
||||
for _, diseaseLocusObject := range diseaseLocusObjectsList{
|
||||
|
||||
locusIdentifierHex := diseaseLocusObject.LocusIdentifier
|
||||
|
||||
locusIdentifier, err := encoding.DecodeHexStringTo3ByteArray(locusIdentifierHex)
|
||||
if (err != nil) { return err }
|
||||
|
||||
for _, genomeIdentifier := range allGenomeIdentifiersList{
|
||||
|
||||
_, _, _, _, _, err := GetPersonPolygenicDiseaseLocusInfoFromGeneticAnalysis(personAnalysisObject, diseaseName, locusIdentifier, genomeIdentifier)
|
||||
if (err != nil) { return err }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traitObjectsList, err := traits.GetTraitObjectsList()
|
||||
|
@ -1138,25 +1004,9 @@ func VerifyCoupleGeneticAnalysis(coupleAnalysisObject geneticAnalysis.CoupleAnal
|
|||
|
||||
for _, genomePairIdentifier := range allGenomePairIdentifiersList{
|
||||
|
||||
_, _, _, _, _, _, err := GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, genomePairIdentifier)
|
||||
_, _, _, _, _, _, _, err := GetOffspringPolygenicDiseaseInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, genomePairIdentifier)
|
||||
if (err != nil) { return err }
|
||||
}
|
||||
|
||||
diseaseLocusObjectsList := diseaseObject.LociList
|
||||
|
||||
for _, diseaseLocusObject := range diseaseLocusObjectsList{
|
||||
|
||||
locusIdentifierHex := diseaseLocusObject.LocusIdentifier
|
||||
|
||||
locusIdentifier, err := encoding.DecodeHexStringTo3ByteArray(locusIdentifierHex)
|
||||
if (err != nil) { return err }
|
||||
|
||||
for _, genomePairIdentifier := range allGenomePairIdentifiersList{
|
||||
|
||||
_, _, _, _, _, err := GetOffspringPolygenicDiseaseLocusInfoFromGeneticAnalysis(coupleAnalysisObject, diseaseName, locusIdentifier, genomePairIdentifier)
|
||||
if (err != nil) { return err }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traitObjectsList, err := traits.GetTraitObjectsList()
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -49,6 +49,29 @@ func ConvertCentimetersToFeetInchesTranslatedString(centimeters float64)(string,
|
|||
return "", errors.New("ConvertCentimetersToFeetInchesTranslatedString called with invalid centimeters.")
|
||||
}
|
||||
|
||||
getInchUnits := func()string{
|
||||
|
||||
if (inputInches == 1){
|
||||
result := translation.TranslateTextFromEnglishToMyLanguage("inch")
|
||||
return result
|
||||
}
|
||||
|
||||
inchesTranslated := translation.TranslateTextFromEnglishToMyLanguage("inches")
|
||||
|
||||
return inchesTranslated
|
||||
}
|
||||
|
||||
inchUnits := getInchUnits()
|
||||
|
||||
inputInchesString := ConvertFloat64ToStringRounded(inputInches, 1)
|
||||
|
||||
if (inputFeet == 0){
|
||||
|
||||
formattedResult := inputInchesString + " " + inchUnits
|
||||
|
||||
return formattedResult, nil
|
||||
}
|
||||
|
||||
getFeetUnits := func()string{
|
||||
|
||||
if (inputFeet <= 1){
|
||||
|
@ -64,22 +87,7 @@ func ConvertCentimetersToFeetInchesTranslatedString(centimeters float64)(string,
|
|||
|
||||
feetUnits := getFeetUnits()
|
||||
|
||||
getInchUnits := func()string{
|
||||
|
||||
if (inputInches == 1){
|
||||
result := translation.TranslateTextFromEnglishToMyLanguage("inch")
|
||||
return result
|
||||
}
|
||||
|
||||
inchesTranslated := translation.TranslateTextFromEnglishToMyLanguage("inches")
|
||||
|
||||
return inchesTranslated
|
||||
}
|
||||
|
||||
inchUnits := getInchUnits()
|
||||
|
||||
inputFeetString := ConvertIntToString(inputFeet)
|
||||
inputInchesString := ConvertFloat64ToStringRounded(inputInches, 1)
|
||||
|
||||
formattedResult := inputFeetString + " " + feetUnits + ", " + inputInchesString + " " + inchUnits
|
||||
|
||||
|
|
|
@ -684,9 +684,7 @@ func GetAnyProfileAttributeIncludingCalculated(attributeName string, getProfileA
|
|||
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
for _, locusRSID := range diseaseLociList{
|
||||
|
||||
locusRSIDString := helpers.ConvertInt64ToString(locusRSID)
|
||||
|
||||
|
@ -723,9 +721,9 @@ func GetAnyProfileAttributeIncludingCalculated(attributeName string, getProfileA
|
|||
userDiseaseLocusValuesMap[locusRSID] = userLocusValueObject
|
||||
}
|
||||
|
||||
anyLocusTested, userDiseaseRiskScore, _, _, err := createPersonGeneticAnalysis.GetPersonGenomePolygenicDiseaseInfo(diseaseLociList, userDiseaseLocusValuesMap, true)
|
||||
neuralNetworkExists, anyLocusTested, userDiseaseRiskScore, _, _, _, err := createPersonGeneticAnalysis.GetPersonGenomePolygenicDiseaseAnalysis(diseaseObject, userDiseaseLocusValuesMap, true)
|
||||
if (err != nil) { return false, 0, "", err }
|
||||
if (anyLocusTested == false){
|
||||
if (neuralNetworkExists == false || anyLocusTested == false){
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -803,9 +801,7 @@ func GetAnyProfileAttributeIncludingCalculated(attributeName string, getProfileA
|
|||
// Map Structure: rsID -> Locus Value
|
||||
userDiseaseLocusValuesMap := make(map[int64]locusValue.LocusValue)
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
for _, locusRSID := range diseaseLociList{
|
||||
|
||||
locusRSIDString := helpers.ConvertInt64ToString(locusRSID)
|
||||
|
||||
|
@ -842,9 +838,9 @@ func GetAnyProfileAttributeIncludingCalculated(attributeName string, getProfileA
|
|||
userDiseaseLocusValuesMap[locusRSID] = newLocusValueObject
|
||||
}
|
||||
|
||||
anyLocusValuesTested, offspringAverageRiskScore, _, err := createCoupleGeneticAnalysis.GetOffspringPolygenicDiseaseInfo_Fast(diseaseLociList, myGenomeLocusValuesMap, userDiseaseLocusValuesMap)
|
||||
neuralNetworkExists, anyLocusValuesTested, offspringAverageRiskScore, _, _, _, _, err := createCoupleGeneticAnalysis.GetOffspringPolygenicDiseaseAnalysis(diseaseObject, myGenomeLocusValuesMap, userDiseaseLocusValuesMap)
|
||||
if (err != nil) { return false, 0, "", err }
|
||||
if (anyLocusValuesTested == false){
|
||||
if (neuralNetworkExists == false || anyLocusValuesTested == false){
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -214,11 +214,9 @@ func UpdateMyExportedProfile(myProfileType string, networkType byte)error{
|
|||
|
||||
lociList := diseaseObject.LociList
|
||||
|
||||
for _, locusObject := range lociList{
|
||||
for _, rsID := range lociList{
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
|
||||
myLociToShareMap[locusRSID] = struct{}{}
|
||||
myLociToShareMap[rsID] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2267,11 +2267,9 @@ func initializeProfileAttributeObjectsList()error{
|
|||
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
for _, rsID := range diseaseLociList{
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
|
||||
shareableRSIDsMap[locusRSID] = struct{}{}
|
||||
shareableRSIDsMap[rsID] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -210,9 +210,7 @@ func TestProfileGeneticReferences(t *testing.T){
|
|||
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
locusRSID := locusObject.LocusRSID
|
||||
for _, locusRSID := range diseaseLociList{
|
||||
|
||||
locusRSIDString := helpers.ConvertInt64ToString(locusRSID)
|
||||
|
||||
|
|
|
@ -21,6 +21,12 @@ var predictionModel_LactoseTolerance []byte
|
|||
//go:embed predictionModels/HeightModel.gob
|
||||
var predictionModel_Height []byte
|
||||
|
||||
//go:embed predictionModels/AutismModel.gob
|
||||
var predictionModel_Autism []byte
|
||||
|
||||
//go:embed predictionModels/HomosexualnessModel.gob
|
||||
var predictionModel_Homosexualness []byte
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -bool: Model exists
|
||||
|
@ -38,6 +44,12 @@ func GetGeneticPredictionModelBytes(traitName string)(bool, []byte){
|
|||
case "Height":{
|
||||
return true, predictionModel_Height
|
||||
}
|
||||
case "Autism":{
|
||||
return true, predictionModel_Autism
|
||||
}
|
||||
case "Homosexualness":{
|
||||
return true, predictionModel_Homosexualness
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
|
@ -65,19 +77,33 @@ func GetPredictionModelDiscreteTraitAccuracyInfoBytes(traitName string)([]byte,
|
|||
return nil, errors.New("GetPredictionModelDiscreteTraitAccuracyInfoBytes called with unknown traitName: " + traitName)
|
||||
}
|
||||
|
||||
|
||||
//go:embed predictionModelAccuracies/HeightModelAccuracy.gob
|
||||
var predictionAccuracy_Height []byte
|
||||
|
||||
// The files returned by this function are .gob encoded geneticPrediction.NumericTraitPredictionAccuracyInfoMap objects
|
||||
func GetPredictionModelNumericTraitAccuracyInfoBytes(traitName string)([]byte, error){
|
||||
//go:embed predictionModelAccuracies/AutismModelAccuracy.gob
|
||||
var predictionAccuracy_Autism []byte
|
||||
|
||||
switch traitName{
|
||||
//go:embed predictionModelAccuracies/HomosexualnessModelAccuracy.gob
|
||||
var predictionAccuracy_Homosexualness []byte
|
||||
|
||||
|
||||
// The files returned by this function are .gob encoded geneticPrediction.NumericAttributePredictionAccuracyInfoMap objects
|
||||
func GetPredictionModelNumericAttributeAccuracyInfoBytes(attributeName string)([]byte, error){
|
||||
|
||||
switch attributeName{
|
||||
case "Height":{
|
||||
return predictionAccuracy_Height, nil
|
||||
}
|
||||
case "Autism":{
|
||||
return predictionAccuracy_Autism, nil
|
||||
}
|
||||
case "Homosexualness":{
|
||||
return predictionAccuracy_Homosexualness, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New("GetPredictionModelNumericTraitAccuracyInfoBytes called with unknown traitName: " + traitName)
|
||||
return nil, errors.New("GetPredictionModelNumericAttributeAccuracyInfoBytes called with unknown attributeName: " + attributeName)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,13 +9,13 @@ import "seekia/internal/genetics/geneticPrediction"
|
|||
|
||||
func TestGeneticPredictionModels(t *testing.T){
|
||||
|
||||
traitNamesList := []string{"Eye Color", "Lactose Tolerance", "Height"}
|
||||
attributeNamesList := []string{"Eye Color", "Lactose Tolerance", "Height", "Autism"}
|
||||
|
||||
for _, traitName := range traitNamesList{
|
||||
for _, attributeName := range attributeNamesList{
|
||||
|
||||
modelFound, modelBytes := geneticPredictionModels.GetGeneticPredictionModelBytes(traitName)
|
||||
modelFound, modelBytes := geneticPredictionModels.GetGeneticPredictionModelBytes(attributeName)
|
||||
if (modelFound == false){
|
||||
t.Fatalf("GetGeneticPredictionModelBytes failed to find model for trait: " + traitName)
|
||||
t.Fatalf("GetGeneticPredictionModelBytes failed to find model for trait: " + attributeName)
|
||||
}
|
||||
|
||||
_, err := geneticPrediction.DecodeBytesToNeuralNetworkObject(modelBytes)
|
||||
|
@ -43,18 +43,18 @@ func TestGeneticPredictionModelAccuracies(t *testing.T){
|
|||
}
|
||||
}
|
||||
|
||||
numericTraitNamesList := []string{"Height"}
|
||||
numericAttributeNamesList := []string{"Height", "Autism", "Homosexualness"}
|
||||
|
||||
for _, traitName := range numericTraitNamesList{
|
||||
for _, attributeName := range numericAttributeNamesList{
|
||||
|
||||
accuracyInfoBytes, err := geneticPredictionModels.GetPredictionModelNumericTraitAccuracyInfoBytes(traitName)
|
||||
accuracyInfoBytes, err := geneticPredictionModels.GetPredictionModelNumericAttributeAccuracyInfoBytes(attributeName)
|
||||
if (err != nil){
|
||||
t.Fatalf("GetPredictionModelNumericTraitAccuracyInfoBytes failed: " + err.Error())
|
||||
t.Fatalf("GetPredictionModelNumericAttributeAccuracyInfoBytes failed: " + err.Error())
|
||||
}
|
||||
|
||||
_, err = geneticPrediction.DecodeBytesToNumericTraitPredictionAccuracyInfoMap(accuracyInfoBytes)
|
||||
_, err = geneticPrediction.DecodeBytesToNumericAttributePredictionAccuracyInfoMap(accuracyInfoBytes)
|
||||
if (err != nil){
|
||||
t.Fatalf("DecodeBytesToNumericTraitPredictionAccuracyInfoMap failed: " + err.Error())
|
||||
t.Fatalf("DecodeBytesToNumericAttributePredictionAccuracyInfoMap failed: " + err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,8 @@
|
|||
|
||||
// attributeLoci provides loci associated with various bodily attributes
|
||||
// For example, this package stores all loci associated with the brain
|
||||
// We can then use this same set of loci to predict all attributes pertaining to the brain, such as autism, depression, anxiety, etc.
|
||||
// We need this package because we can't have packages that import from polygenicDiseases->traits and traits->polygenicDiseases
|
||||
|
||||
package attributeLoci
|
||||
|
605
resources/geneticReferences/attributeLoci/autism.go
Normal file
605
resources/geneticReferences/attributeLoci/autism.go
Normal file
|
@ -0,0 +1,605 @@
|
|||
package attributeLoci
|
||||
|
||||
import "maps"
|
||||
|
||||
// Outputs:
|
||||
// -map[int64]map[string]string
|
||||
// -Map Structure: rsID -> map[ReferenceName]ReferenceLink
|
||||
func GetAutismLoci()map[int64]map[string]string{
|
||||
|
||||
// Map Structure: rsID -> (map[Reference Name]Reference Link)
|
||||
locusReferencesMap := make(map[int64]map[string]string)
|
||||
|
||||
locus1_ReferencesMap := make(map[string]string)
|
||||
locus1_ReferencesMap["SNPedia.com - rs10513025"] = "https://www.snpedia.com/index.php/Rs10513025"
|
||||
|
||||
locusReferencesMap[10513025] = locus1_ReferencesMap
|
||||
|
||||
locus2_ReferencesMap := make(map[string]string)
|
||||
locus2_ReferencesMap["SNPedia.com - rs2710102"] = "https://www.snpedia.com/index.php/Rs2710102"
|
||||
|
||||
locusReferencesMap[2710102] = locus2_ReferencesMap
|
||||
|
||||
locus3_ReferencesMap := make(map[string]string)
|
||||
locus3_ReferencesMap["SNPedia.com - rs7794745"] = "https://www.snpedia.com/index.php/Rs7794745"
|
||||
|
||||
locusReferencesMap[7794745] = locus3_ReferencesMap
|
||||
|
||||
locus4_ReferencesMap := make(map[string]string)
|
||||
locus4_ReferencesMap["SNPedia.com - rs1858830"] = "https://www.snpedia.com/index.php/Rs1858830"
|
||||
|
||||
locusReferencesMap[1858830] = locus4_ReferencesMap
|
||||
|
||||
locus5_ReferencesMap := make(map[string]string)
|
||||
locus5_ReferencesMap["SNPedia.com - rs1322784"] = "https://www.snpedia.com/index.php/Rs1322784"
|
||||
|
||||
locusReferencesMap[1322784] = locus5_ReferencesMap
|
||||
|
||||
locus6_ReferencesMap := make(map[string]string)
|
||||
locus6_ReferencesMap["SNPedia.com - rs1804197"] = "https://www.snpedia.com/index.php/Rs1804197"
|
||||
|
||||
locusReferencesMap[1804197] = locus6_ReferencesMap
|
||||
|
||||
locus7_ReferencesMap := make(map[string]string)
|
||||
locus7_ReferencesMap["SNPedia.com - rs265981"] = "https://www.snpedia.com/index.php/Rs265981"
|
||||
|
||||
locusReferencesMap[265981] = locus7_ReferencesMap
|
||||
|
||||
locus8_ReferencesMap := make(map[string]string)
|
||||
locus8_ReferencesMap["SNPedia.com - rs4532"] = "https://www.snpedia.com/index.php/Rs4532"
|
||||
|
||||
locusReferencesMap[4532] = locus8_ReferencesMap
|
||||
|
||||
locus9_ReferencesMap := make(map[string]string)
|
||||
locus9_ReferencesMap["SNPedia.com - rs686"] = "https://www.snpedia.com/index.php/Rs686"
|
||||
|
||||
locusReferencesMap[686] = locus9_ReferencesMap
|
||||
|
||||
locus10_ReferencesMap := make(map[string]string)
|
||||
locus10_ReferencesMap["SNPedia.com - rs6766410"] = "https://www.snpedia.com/index.php/Rs6766410"
|
||||
|
||||
locusReferencesMap[6766410] = locus10_ReferencesMap
|
||||
|
||||
locus11_ReferencesMap := make(map[string]string)
|
||||
locus11_ReferencesMap["SNPedia.com - rs6807362"] = "https://www.snpedia.com/index.php/Rs6807362"
|
||||
|
||||
locusReferencesMap[6807362] = locus11_ReferencesMap
|
||||
|
||||
locus12_ReferencesMap := make(map[string]string)
|
||||
locus12_ReferencesMap["SNPedia.com - rs1143674"] = "https://www.snpedia.com/index.php/Rs1143674"
|
||||
|
||||
locusReferencesMap[1143674] = locus12_ReferencesMap
|
||||
|
||||
locus13_ReferencesMap := make(map[string]string)
|
||||
locus13_ReferencesMap["SNPedia.com - rs2745557"] = "https://www.snpedia.com/index.php/Rs2745557"
|
||||
|
||||
locusReferencesMap[2745557] = locus13_ReferencesMap
|
||||
|
||||
locus14_ReferencesMap := make(map[string]string)
|
||||
locus14_ReferencesMap["SNPedia.com - rs2217262"] = "https://www.snpedia.com/index.php/Rs2217262"
|
||||
|
||||
locusReferencesMap[2217262] = locus14_ReferencesMap
|
||||
|
||||
locus15_ReferencesMap := make(map[string]string)
|
||||
locus15_ReferencesMap["SNPedia.com - rs373126732"] = "https://www.snpedia.com/index.php/Rs373126732"
|
||||
|
||||
locusReferencesMap[373126732] = locus15_ReferencesMap
|
||||
|
||||
locus16_ReferencesMap := make(map[string]string)
|
||||
locus16_ReferencesMap["SNPedia.com - rs184718561"] = "https://www.snpedia.com/index.php/Rs184718561"
|
||||
|
||||
locusReferencesMap[184718561] = locus16_ReferencesMap
|
||||
|
||||
locus17_ReferencesMap := make(map[string]string)
|
||||
locus17_ReferencesMap["SNPedia.com - rs1445442"] = "https://www.snpedia.com/index.php/Rs1445442"
|
||||
|
||||
locusReferencesMap[1445442] = locus17_ReferencesMap
|
||||
|
||||
locus18_ReferencesMap := make(map[string]string)
|
||||
locus18_ReferencesMap["SNPedia.com - rs2421826"] = "https://www.snpedia.com/index.php/Rs2421826"
|
||||
|
||||
locusReferencesMap[2421826] = locus18_ReferencesMap
|
||||
|
||||
locus19_ReferencesMap := make(map[string]string)
|
||||
locus19_ReferencesMap["SNPedia.com - rs1358054"] = "https://www.snpedia.com/index.php/Rs1358054"
|
||||
|
||||
locusReferencesMap[1358054] = locus19_ReferencesMap
|
||||
|
||||
locus20_ReferencesMap := make(map[string]string)
|
||||
locus20_ReferencesMap["SNPedia.com - rs722628"] = "https://www.snpedia.com/index.php/Rs722628"
|
||||
|
||||
locusReferencesMap[722628] = locus20_ReferencesMap
|
||||
|
||||
locus21_ReferencesMap := make(map[string]string)
|
||||
locus21_ReferencesMap["SNPedia.com - rs536861"] = "https://www.snpedia.com/index.php/Rs536861"
|
||||
|
||||
locusReferencesMap[536861] = locus21_ReferencesMap
|
||||
|
||||
locus22_ReferencesMap := make(map[string]string)
|
||||
locus22_ReferencesMap["SNPedia.com - rs757972971"] = "https://www.snpedia.com/index.php/Rs757972971"
|
||||
|
||||
locusReferencesMap[757972971] = locus22_ReferencesMap
|
||||
|
||||
|
||||
referencesMap_LocusList1 := make(map[string]string)
|
||||
referencesMap_LocusList1["Understanding the impact of SNPs associated with autism spectrum disorder on biological pathways in the human fetal and adult cortex"] = "https://www.nature.com/articles/s41598-021-95447-z"
|
||||
|
||||
lociList1 := []int64{
|
||||
13217619,
|
||||
115329265,
|
||||
116137698,
|
||||
141342723,
|
||||
75782365,
|
||||
151267808,
|
||||
7746199,
|
||||
114115252,
|
||||
4298967,
|
||||
1782810,
|
||||
6921919,
|
||||
9467711,
|
||||
115707823,
|
||||
116633139,
|
||||
115123779,
|
||||
116326873,
|
||||
9834970,
|
||||
144762289,
|
||||
9348739,
|
||||
4481150,
|
||||
12129573,
|
||||
116408368,
|
||||
11191419,
|
||||
115242751,
|
||||
116385615,
|
||||
114882497,
|
||||
114867672,
|
||||
12658451,
|
||||
202906,
|
||||
13212562,
|
||||
7085104,
|
||||
1702294,
|
||||
114276265,
|
||||
116427960,
|
||||
59574136,
|
||||
114041423,
|
||||
7531118,
|
||||
114964506,
|
||||
111639056,
|
||||
6939532,
|
||||
6940116,
|
||||
116663187,
|
||||
114904464,
|
||||
145547914,
|
||||
9269271,
|
||||
114963521,
|
||||
140502984,
|
||||
61867293,
|
||||
115035678,
|
||||
9274390,
|
||||
11688767,
|
||||
78110044,
|
||||
150680405,
|
||||
10883832,
|
||||
7752195,
|
||||
115497191,
|
||||
116676919,
|
||||
11191582,
|
||||
115344853,
|
||||
144911693,
|
||||
71395455,
|
||||
5758265,
|
||||
2007044,
|
||||
149979052,
|
||||
115682897,
|
||||
3001723,
|
||||
1024582,
|
||||
115625073,
|
||||
9273177,
|
||||
61472021,
|
||||
12668848,
|
||||
184153866,
|
||||
115558405,
|
||||
150430679,
|
||||
115687605,
|
||||
35324223,
|
||||
9274299,
|
||||
138984909,
|
||||
145076523,
|
||||
55661361,
|
||||
911186,
|
||||
144304366,
|
||||
10149470,
|
||||
144660248,
|
||||
13218591,
|
||||
114455101,
|
||||
185717927,
|
||||
144649399,
|
||||
114086406,
|
||||
11682175,
|
||||
142972412,
|
||||
138748649,
|
||||
7405404,
|
||||
11693528,
|
||||
12958048,
|
||||
35225200,
|
||||
114950038,
|
||||
140865314,
|
||||
4129585,
|
||||
12887734,
|
||||
36057735,
|
||||
115052633,
|
||||
186129480,
|
||||
2507989,
|
||||
2021722,
|
||||
140505938,
|
||||
2388334,
|
||||
3617,
|
||||
114274203,
|
||||
281768,
|
||||
115937317,
|
||||
144018888,
|
||||
2535629,
|
||||
4906364,
|
||||
180778602,
|
||||
707939,
|
||||
8084351,
|
||||
80318442,
|
||||
186229361,
|
||||
9461856,
|
||||
113397282,
|
||||
28681284,
|
||||
113205291,
|
||||
2851447,
|
||||
4380187,
|
||||
115960997,
|
||||
1793889,
|
||||
142790902,
|
||||
111312615,
|
||||
144532965,
|
||||
75968099,
|
||||
115661163,
|
||||
1518367,
|
||||
193267147,
|
||||
41293179,
|
||||
200986,
|
||||
34787248,
|
||||
140364877,
|
||||
13240464,
|
||||
1625579,
|
||||
4702,
|
||||
2514218,
|
||||
778353,
|
||||
325506,
|
||||
182908437,
|
||||
149721896,
|
||||
6434928,
|
||||
4713071,
|
||||
11753207,
|
||||
191843781,
|
||||
116182620,
|
||||
2760981,
|
||||
116067082,
|
||||
142601889,
|
||||
147976543,
|
||||
116254153,
|
||||
8054556,
|
||||
114204022,
|
||||
115165987,
|
||||
9636107,
|
||||
41563,
|
||||
35828350,
|
||||
764284,
|
||||
115325719,
|
||||
7193263,
|
||||
149915948,
|
||||
17843707,
|
||||
79879286,
|
||||
631399,
|
||||
732381,
|
||||
1150688,
|
||||
189600472,
|
||||
3798869,
|
||||
5757717,
|
||||
145501595,
|
||||
4642619,
|
||||
117616320,
|
||||
12704290,
|
||||
2176546,
|
||||
149787317,
|
||||
11570190,
|
||||
4391122,
|
||||
7071123,
|
||||
12712388,
|
||||
4307059,
|
||||
369637,
|
||||
114291394,
|
||||
11740474,
|
||||
12925872,
|
||||
116460775,
|
||||
114838832,
|
||||
10791097,
|
||||
35610290,
|
||||
114812317,
|
||||
9469174,
|
||||
7801375,
|
||||
114508985,
|
||||
6704768,
|
||||
4580973,
|
||||
147875011,
|
||||
7893279,
|
||||
12966547,
|
||||
9922678,
|
||||
111294930,
|
||||
6047287,
|
||||
34215985,
|
||||
2693698,
|
||||
12826178,
|
||||
2237234,
|
||||
11210892,
|
||||
67756423,
|
||||
9787523,
|
||||
10108980,
|
||||
2057884,
|
||||
1498232,
|
||||
8042374,
|
||||
142520578,
|
||||
114771361,
|
||||
114810457,
|
||||
17194490,
|
||||
145470632,
|
||||
36063234,
|
||||
2332700,
|
||||
1615350,
|
||||
3735025,
|
||||
115283957,
|
||||
75059851,
|
||||
1730054,
|
||||
116593970,
|
||||
4523957,
|
||||
169738,
|
||||
35346733,
|
||||
12954356,
|
||||
7907645,
|
||||
2910032,
|
||||
9270074,
|
||||
1899546,
|
||||
6071524,
|
||||
11874716,
|
||||
72761442,
|
||||
3132556,
|
||||
116139966,
|
||||
139547629,
|
||||
28724212,
|
||||
6855246,
|
||||
72934570,
|
||||
147793969,
|
||||
115487448,
|
||||
4619651,
|
||||
7521492,
|
||||
2103655,
|
||||
880090,
|
||||
1806153,
|
||||
11787216,
|
||||
115915654,
|
||||
11223651,
|
||||
62378245,
|
||||
8009147,
|
||||
7191183,
|
||||
77502336,
|
||||
3849046,
|
||||
1131275,
|
||||
61747867,
|
||||
116047537,
|
||||
41293330,
|
||||
61789073,
|
||||
7914558,
|
||||
10043984,
|
||||
10514301,
|
||||
117956829,
|
||||
4647903,
|
||||
4916723,
|
||||
28669119,
|
||||
35774874,
|
||||
4244354,
|
||||
1452075,
|
||||
56223946,
|
||||
2434529,
|
||||
115641444,
|
||||
149998036,
|
||||
184123737,
|
||||
10994359,
|
||||
9360557,
|
||||
80256351,
|
||||
6125656,
|
||||
247910,
|
||||
3812984,
|
||||
915057,
|
||||
17659437,
|
||||
11641947,
|
||||
139099016,
|
||||
72687362,
|
||||
57709857,
|
||||
11210195,
|
||||
3020736,
|
||||
12592967,
|
||||
5995756,
|
||||
385492,
|
||||
115443066,
|
||||
9371601,
|
||||
59979824,
|
||||
6694545,
|
||||
1484144,
|
||||
832190,
|
||||
9267057,
|
||||
4309187,
|
||||
149544854,
|
||||
116502302,
|
||||
191269336,
|
||||
1006737,
|
||||
10265001,
|
||||
6969410,
|
||||
1080500,
|
||||
171748,
|
||||
139480376,
|
||||
17292804,
|
||||
174592,
|
||||
1620977,
|
||||
184538485,
|
||||
191239160,
|
||||
301798,
|
||||
10211550,
|
||||
10994397,
|
||||
9677504,
|
||||
144158419,
|
||||
2098651,
|
||||
8321,
|
||||
11231640,
|
||||
77135925,
|
||||
12474906,
|
||||
2300861,
|
||||
2391769,
|
||||
10520163,
|
||||
9607782,
|
||||
55648125,
|
||||
10099100,
|
||||
16854048,
|
||||
35131895,
|
||||
1977199,
|
||||
145607970,
|
||||
115569272,
|
||||
116552815,
|
||||
6803008,
|
||||
35998080,
|
||||
10791111,
|
||||
2944591,
|
||||
1353545,
|
||||
115437294,
|
||||
133047,
|
||||
9274657,
|
||||
11191580,
|
||||
11191454,
|
||||
7618871,
|
||||
10745841,
|
||||
61882743,
|
||||
116755193,
|
||||
142462188,
|
||||
7200826,
|
||||
27419,
|
||||
2414718,
|
||||
2842198,
|
||||
12552,
|
||||
395138,
|
||||
760648,
|
||||
1002656,
|
||||
2898883,
|
||||
13072940,
|
||||
12443170,
|
||||
114441450,
|
||||
146201420,
|
||||
184981897,
|
||||
138850297,
|
||||
8032315,
|
||||
7184114,
|
||||
115136442,
|
||||
2767713,
|
||||
2828478,
|
||||
9879311,
|
||||
114142645,
|
||||
111977918,
|
||||
7819570,
|
||||
12522290,
|
||||
112209031,
|
||||
10491964,
|
||||
11658257,
|
||||
62526783,
|
||||
6471814,
|
||||
11866581,
|
||||
12894153,
|
||||
2391734,
|
||||
2522831,
|
||||
2003490,
|
||||
301799,
|
||||
1226412,
|
||||
1950829,
|
||||
8453,
|
||||
926938,
|
||||
6537825,
|
||||
111931861,
|
||||
115963308,
|
||||
149961934,
|
||||
61847307,
|
||||
146827975,
|
||||
1339227,
|
||||
36350,
|
||||
7432375,
|
||||
9656169,
|
||||
28758902,
|
||||
427691,
|
||||
2293751,
|
||||
182087722,
|
||||
73416724,
|
||||
61884307,
|
||||
188190243,
|
||||
41294271,
|
||||
114830752,
|
||||
7004633,
|
||||
7785663,
|
||||
8066384,
|
||||
188099135,
|
||||
4730387,
|
||||
11887562,
|
||||
2801578,
|
||||
4242470,
|
||||
746839,
|
||||
3827735,
|
||||
11582563,
|
||||
11102807,
|
||||
7511633,
|
||||
11102800,
|
||||
11585926,
|
||||
6661053,
|
||||
11589568,
|
||||
4141463,
|
||||
201910565,
|
||||
71190156,
|
||||
353547,
|
||||
880446,
|
||||
2115780,
|
||||
114277634,
|
||||
140849564,
|
||||
76994193,
|
||||
114875775,
|
||||
7122181,
|
||||
221902,
|
||||
12576775,
|
||||
10503253,
|
||||
2799573,
|
||||
4495234,
|
||||
4526442,
|
||||
4682973,
|
||||
12898460,
|
||||
2047568,
|
||||
2910032,
|
||||
1501361,
|
||||
}
|
||||
|
||||
for _, rsID := range lociList1{
|
||||
|
||||
existingMap, exists := locusReferencesMap[rsID]
|
||||
if (exists == false){
|
||||
locusReferencesMap[rsID] = maps.Clone(referencesMap_LocusList1)
|
||||
} else {
|
||||
|
||||
// We merge the maps
|
||||
|
||||
for key, value := range referencesMap_LocusList1{
|
||||
existingMap[key] = value
|
||||
}
|
||||
|
||||
locusReferencesMap[rsID] = existingMap
|
||||
}
|
||||
}
|
||||
|
||||
return locusReferencesMap
|
||||
}
|
||||
|
||||
|
|
@ -199,6 +199,7 @@ func TestGeneticReferences(t *testing.T){
|
|||
diseaseName := diseaseObject.DiseaseName
|
||||
diseaseDescription := diseaseObject.DiseaseDescription
|
||||
diseaseEffectedSex := diseaseObject.EffectedSex
|
||||
diseaseLocusReferencesMap := diseaseObject.LocusReferencesMap
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
diseaseReferencesMap := diseaseObject.References
|
||||
|
||||
|
@ -218,82 +219,34 @@ func TestGeneticReferences(t *testing.T){
|
|||
t.Fatalf("PolygenicDisease effected sex is invalid: " + diseaseEffectedSex)
|
||||
}
|
||||
|
||||
for rsID, referencesMap := range diseaseLocusReferencesMap{
|
||||
|
||||
containsItem := slices.Contains(diseaseLociList, rsID)
|
||||
if (containsItem == false){
|
||||
t.Fatalf("Polygenic disease diseaseLocusReferencesMap contains disease locus that is not inside of the disease's loci list.")
|
||||
}
|
||||
|
||||
allRSIDsMap[rsID] = struct{}{}
|
||||
|
||||
referencesAreValid := verifyReferencesMap(referencesMap)
|
||||
if (referencesAreValid == false){
|
||||
t.Fatalf("PolygenicDisease references map is invalid for disease locus.")
|
||||
}
|
||||
}
|
||||
|
||||
containsDuplicates, _ := helpers.CheckIfListContainsDuplicates(diseaseLociList)
|
||||
if (containsDuplicates == true){
|
||||
t.Fatalf("Polygenic disease object contains diseaseLociList with duplicate rsIDs.")
|
||||
}
|
||||
|
||||
if (len(diseaseLocusReferencesMap) > len(diseaseLociList)){
|
||||
t.Fatalf("Polygenic disease contains locus references map that is longer than the diseaseLociList")
|
||||
}
|
||||
|
||||
referencesAreValid := verifyReferencesMap(diseaseReferencesMap)
|
||||
if (referencesAreValid == false){
|
||||
t.Fatalf("PolygenicDisease references map is invalid for disease: " + diseaseName)
|
||||
}
|
||||
|
||||
// We use this map to make sure each disease locus references a unique rsid
|
||||
allPolygenicDiseaseRSIDsMap := make(map[int64]struct{})
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
locusIdentifier := locusObject.LocusIdentifier
|
||||
locusRSID := locusObject.LocusRSID
|
||||
riskWeightsMap := locusObject.RiskWeightsMap
|
||||
oddsRatiosMap := locusObject.OddsRatiosMap
|
||||
minimumWeight := locusObject.MinimumRiskWeight
|
||||
maximumWeight := locusObject.MaximumRiskWeight
|
||||
|
||||
allRSIDsMap[locusRSID] = struct{}{}
|
||||
|
||||
identifierIsValid := verifyIdentifier(locusIdentifier)
|
||||
if (identifierIsValid == false){
|
||||
t.Fatalf(diseaseName + " Invalid locus identifier found: " + locusIdentifier)
|
||||
}
|
||||
|
||||
_, exists := allIdentifiersMap[locusIdentifier]
|
||||
if (exists == true){
|
||||
t.Fatalf(diseaseName + " Duplicate locus identifier found: " + locusIdentifier)
|
||||
}
|
||||
allIdentifiersMap[locusIdentifier] = struct{}{}
|
||||
|
||||
_, exists = allPolygenicDiseaseRSIDsMap[locusRSID]
|
||||
if (exists == true){
|
||||
rsidString := helpers.ConvertInt64ToString(locusRSID)
|
||||
t.Fatalf(diseaseName + " RSID Collision found: " + rsidString)
|
||||
}
|
||||
|
||||
allPolygenicDiseaseRSIDsMap[locusRSID] = struct{}{}
|
||||
|
||||
if (len(riskWeightsMap) == 0){
|
||||
t.Fatalf("Empty base weights map found: " + locusIdentifier)
|
||||
}
|
||||
|
||||
trueMinimumWeight := 100000
|
||||
trueMaximumWeight := -100000
|
||||
|
||||
for basePair, basePairWeight := range riskWeightsMap{
|
||||
|
||||
isValid := verifyBasePair(basePair)
|
||||
if (isValid == false){
|
||||
t.Fatalf("Base pair weights map contains invalid base pair: " + locusIdentifier)
|
||||
}
|
||||
|
||||
if (basePairWeight < trueMinimumWeight){
|
||||
trueMinimumWeight = basePairWeight
|
||||
}
|
||||
if (basePairWeight > trueMaximumWeight){
|
||||
trueMaximumWeight = basePairWeight
|
||||
}
|
||||
}
|
||||
|
||||
if (trueMinimumWeight != minimumWeight){
|
||||
t.Fatalf(diseaseName + ": Invalid minimum base pair weight found: " + locusIdentifier)
|
||||
}
|
||||
if (trueMaximumWeight != maximumWeight){
|
||||
t.Fatalf(diseaseName + ": Invalid maximum base pair weight found: " + locusIdentifier)
|
||||
}
|
||||
|
||||
for basePair, _ := range oddsRatiosMap{
|
||||
isValid := verifyBasePair(basePair)
|
||||
if (isValid == false){
|
||||
t.Fatalf("Odds ratio weights map contains invalid base pair: " + locusIdentifier)
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Make sure that duplicate base pairs have same weight, odds ratios and probabilities
|
||||
}
|
||||
}
|
||||
|
||||
err = traits.InitializeTraitVariables()
|
||||
|
|
Binary file not shown.
|
@ -43,7 +43,8 @@ func AddLocusMetadata(inputLociToAddList []locusMetadata.LocusMetadata)(int, []b
|
|||
|
||||
_, exists := newLocusMetadataRSIDsMap[rsID]
|
||||
if (exists == true){
|
||||
return 0, nil, errors.New("inputLociToAddList contains multiple locus metadatas with a duplicate rsID.")
|
||||
rsIDString := helpers.ConvertInt64ToString(rsID)
|
||||
return 0, nil, errors.New("inputLociToAddList contains multiple locus metadatas with a duplicate rsID: " + rsIDString)
|
||||
}
|
||||
|
||||
newLocusMetadataRSIDsMap[rsID] = struct{}{}
|
||||
|
|
51
resources/geneticReferences/polygenicDiseases/autism.go
Normal file
51
resources/geneticReferences/polygenicDiseases/autism.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package polygenicDiseases
|
||||
|
||||
import "errors"
|
||||
|
||||
import "seekia/resources/geneticReferences/attributeLoci"
|
||||
|
||||
import "seekia/internal/helpers"
|
||||
|
||||
|
||||
func getAutismDiseaseObject()PolygenicDisease{
|
||||
|
||||
autismLocusReferencesMap := attributeLoci.GetAutismLoci()
|
||||
|
||||
autismLociList := helpers.GetListOfMapKeys(autismLocusReferencesMap)
|
||||
|
||||
referencesMap := make(map[string]string)
|
||||
referencesMap["SNPedia.com - Autism"] = "https://www.snpedia.com/index.php/Autism"
|
||||
|
||||
// https://www.cdc.gov/mmwr/volumes/72/ss/ss7202a1.htm
|
||||
// For 2020, one in 36 children aged 8 years (approximately 4% of boys and 1% of girls) was estimated to have ASD.
|
||||
|
||||
getAverageRiskProbabilitiesFunction := func(maleOrFemale string, inputAge int)(float64, error){
|
||||
|
||||
if (maleOrFemale == "Male"){
|
||||
return 0.04, nil
|
||||
}
|
||||
|
||||
if (maleOrFemale != "Female"){
|
||||
return 0, errors.New("Trying to get breast cancer risk probability for invalid maleOrFemale: " + maleOrFemale)
|
||||
}
|
||||
|
||||
//TODO: Add different probabilities per age
|
||||
|
||||
return 0.01, nil
|
||||
}
|
||||
|
||||
autismObject := PolygenicDisease{
|
||||
|
||||
DiseaseName: "Autism",
|
||||
EffectedSex: "Both",
|
||||
DiseaseDescription: "A mental disorder characterized by inability to engage in normal social interactions and intense self-absorption, and usually accompanied by other symptoms such as language dysfunctions and repetitive behavior.",
|
||||
// Taken from: The American Heritage® Dictionary of the English Language, 5th Edition
|
||||
LocusReferencesMap: autismLocusReferencesMap,
|
||||
LociList: autismLociList,
|
||||
GetAverageRiskProbabilitiesFunction: getAverageRiskProbabilitiesFunction,
|
||||
References: referencesMap,
|
||||
}
|
||||
|
||||
return autismObject
|
||||
}
|
||||
|
|
@ -2,863 +2,143 @@ package polygenicDiseases
|
|||
|
||||
import "errors"
|
||||
|
||||
import "seekia/internal/helpers"
|
||||
|
||||
|
||||
func getBreastCancerDiseaseObject()PolygenicDisease{
|
||||
|
||||
// Map Structure: rsID -> (map[Reference Name]Reference Link)
|
||||
locusReferencesMap := make(map[int64]map[string]string)
|
||||
|
||||
locus1_ReferencesMap := make(map[string]string)
|
||||
locus1_ReferencesMap["SNPedia.com - rs16942"] = "https://www.snpedia.com/index.php/Rs16942"
|
||||
|
||||
locus1_RiskWeightsMap := make(map[string]int)
|
||||
locus1_RiskWeightsMap["T;T"] = 0
|
||||
locus1_RiskWeightsMap["T;C"] = 1
|
||||
locus1_RiskWeightsMap["C;T"] = 1
|
||||
locus1_RiskWeightsMap["C;C"] = 1
|
||||
|
||||
locus1_OddsRatiosMap := make(map[string]float64)
|
||||
locus1_OddsRatiosMap["T;T"] = 1
|
||||
locus1_OddsRatiosMap["T;C"] = 1.14
|
||||
locus1_OddsRatiosMap["C;T"] = 1.14
|
||||
locus1_OddsRatiosMap["C;C"] = 1.28
|
||||
|
||||
locus1_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus1_BasePairProbabilitiesMap["T;T"] = .45
|
||||
locus1_BasePairProbabilitiesMap["T;C"] = .45
|
||||
locus1_BasePairProbabilitiesMap["C;T"] = .45
|
||||
locus1_BasePairProbabilitiesMap["C;C"] = .10
|
||||
|
||||
locus1_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "d7891c",
|
||||
LocusRSID: 16942,
|
||||
RiskWeightsMap: locus1_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 1,
|
||||
OddsRatiosMap: locus1_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus1_BasePairProbabilitiesMap,
|
||||
References: locus1_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[16942] = locus1_ReferencesMap
|
||||
|
||||
locus2_ReferencesMap := make(map[string]string)
|
||||
locus2_ReferencesMap["SNPedia.com - rs1045485"] = "https://www.snpedia.com/index.php/Rs1045485"
|
||||
|
||||
locus2_RiskWeightsMap := make(map[string]int)
|
||||
locus2_RiskWeightsMap["C;C"] = -2
|
||||
locus2_RiskWeightsMap["C;G"] = -1
|
||||
locus2_RiskWeightsMap["G;C"] = -1
|
||||
locus2_RiskWeightsMap["G;G"] = 0
|
||||
|
||||
locus2_OddsRatiosMap := make(map[string]float64)
|
||||
|
||||
locus2_OddsRatiosMap["C;C"] = 0.74
|
||||
locus2_OddsRatiosMap["C;G"] = 0.89
|
||||
locus2_OddsRatiosMap["G;C"] = 0.89
|
||||
locus2_OddsRatiosMap["G;G"] = 1
|
||||
|
||||
locus2_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus2_BasePairProbabilitiesMap["C;C"] = .01
|
||||
locus2_BasePairProbabilitiesMap["C;G"] = .04
|
||||
locus2_BasePairProbabilitiesMap["G;C"] = .04
|
||||
locus2_BasePairProbabilitiesMap["G;G"] = .95
|
||||
|
||||
locus2_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "41c164",
|
||||
LocusRSID: 1045485,
|
||||
RiskWeightsMap: locus2_RiskWeightsMap,
|
||||
MinimumRiskWeight: -2,
|
||||
MaximumRiskWeight: 0,
|
||||
OddsRatiosMap: locus2_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus2_BasePairProbabilitiesMap,
|
||||
References: locus2_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[1045485] = locus2_ReferencesMap
|
||||
|
||||
locus3_ReferencesMap := make(map[string]string)
|
||||
locus3_ReferencesMap["SNPedia.com - rs34330"] = "https://www.snpedia.com/index.php/Rs34330"
|
||||
|
||||
locus3_RiskWeightsMap := make(map[string]int)
|
||||
locus3_RiskWeightsMap["C;C"] = 0
|
||||
locus3_RiskWeightsMap["T;T"] = 1
|
||||
|
||||
locus3_OddsRatiosMap := make(map[string]float64)
|
||||
locus3_OddsRatiosMap["C;C"] = 0
|
||||
locus3_OddsRatiosMap["T;T"] = 1.22
|
||||
|
||||
locus3_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus3_BasePairProbabilitiesMap["C;C"] = .40
|
||||
locus3_BasePairProbabilitiesMap["C;T"] = .45
|
||||
locus3_BasePairProbabilitiesMap["T;C"] = .45
|
||||
locus3_BasePairProbabilitiesMap["T;T"] = .15
|
||||
|
||||
locus3_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "f3a097",
|
||||
LocusRSID: 34330,
|
||||
RiskWeightsMap: locus3_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 1,
|
||||
OddsRatiosMap: locus3_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus3_BasePairProbabilitiesMap,
|
||||
References: locus3_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[34330] = locus3_ReferencesMap
|
||||
|
||||
locus4_ReferencesMap := make(map[string]string)
|
||||
locus4_ReferencesMap["SNPedia.com - rs144848"] = "https://www.snpedia.com/index.php/Rs144848"
|
||||
|
||||
locus4_RiskWeightsMap := make(map[string]int)
|
||||
locus4_RiskWeightsMap["A;A"] = 0
|
||||
locus4_RiskWeightsMap["C;A"] = 1
|
||||
locus4_RiskWeightsMap["A;C"] = 1
|
||||
locus4_RiskWeightsMap["C;C"] = 2
|
||||
|
||||
locus4_OddsRatiosMap := make(map[string]float64)
|
||||
locus4_OddsRatiosMap["A;A"] = 1
|
||||
locus4_OddsRatiosMap["A;C"] = 1.14
|
||||
locus4_OddsRatiosMap["C;A"] = 1.14
|
||||
locus4_OddsRatiosMap["C;C"] = 1.31
|
||||
|
||||
locus4_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus4_BasePairProbabilitiesMap["A;A"] = .55
|
||||
locus4_BasePairProbabilitiesMap["C;A"] = .36
|
||||
locus4_BasePairProbabilitiesMap["A;C"] = .36
|
||||
locus4_BasePairProbabilitiesMap["C;C"] = .09
|
||||
|
||||
locus4_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "d4626f",
|
||||
LocusRSID: 144848,
|
||||
RiskWeightsMap: locus4_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus4_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus4_BasePairProbabilitiesMap,
|
||||
References: locus4_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[144848] = locus4_ReferencesMap
|
||||
|
||||
locus5_ReferencesMap := make(map[string]string)
|
||||
locus5_ReferencesMap["SNPedia.com - rs766173"] = "https://www.snpedia.com/index.php/Rs766173"
|
||||
|
||||
locus5_RiskWeightsMap := make(map[string]int)
|
||||
locus5_RiskWeightsMap["A;A"] = 0
|
||||
locus5_RiskWeightsMap["A;C"] = 1
|
||||
locus5_RiskWeightsMap["C;A"] = 1
|
||||
locus5_RiskWeightsMap["C;C"] = 2
|
||||
|
||||
locus5_OddsRatiosMap := make(map[string]float64)
|
||||
locus5_OddsRatiosMap["A;A"] = 1
|
||||
locus5_OddsRatiosMap["A;C"] = 1.14
|
||||
locus5_OddsRatiosMap["C;A"] = 1.14
|
||||
locus5_OddsRatiosMap["C;C"] = 1.28
|
||||
|
||||
locus5_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus5_BasePairProbabilitiesMap["A;A"] = .85
|
||||
locus5_BasePairProbabilitiesMap["A;C"] = .13
|
||||
locus5_BasePairProbabilitiesMap["C;A"] = .13
|
||||
locus5_BasePairProbabilitiesMap["C;C"] = .02
|
||||
|
||||
locus5_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "84aaa4",
|
||||
LocusRSID: 766173,
|
||||
RiskWeightsMap: locus5_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus5_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus5_BasePairProbabilitiesMap,
|
||||
References: locus5_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[766173] = locus5_ReferencesMap
|
||||
|
||||
locus6_ReferencesMap := make(map[string]string)
|
||||
locus6_ReferencesMap["SNPedia.com - rs1799950"] = "https://www.snpedia.com/index.php/Rs1799950"
|
||||
|
||||
locus6_RiskWeightsMap := make(map[string]int)
|
||||
locus6_RiskWeightsMap["T;T"] = 0
|
||||
locus6_RiskWeightsMap["T;C"] = 1
|
||||
locus6_RiskWeightsMap["C;T"] = 1
|
||||
locus6_RiskWeightsMap["C;C"] = 2
|
||||
|
||||
locus6_OddsRatiosMap := make(map[string]float64)
|
||||
locus6_OddsRatiosMap["T;T"] = 1
|
||||
locus6_OddsRatiosMap["T;C"] = 1.5
|
||||
locus6_OddsRatiosMap["C;T"] = 1.5
|
||||
locus6_OddsRatiosMap["C;C"] = 1.72
|
||||
|
||||
locus6_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus6_BasePairProbabilitiesMap["T;T"] = .98
|
||||
locus6_BasePairProbabilitiesMap["T;C"] = .02
|
||||
locus6_BasePairProbabilitiesMap["C;T"] = .02
|
||||
locus6_BasePairProbabilitiesMap["C;C"] = .001
|
||||
|
||||
locus6_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "c8de7a",
|
||||
LocusRSID: 1799950,
|
||||
RiskWeightsMap: locus6_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus6_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus6_BasePairProbabilitiesMap,
|
||||
References: locus6_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[1799950] = locus6_ReferencesMap
|
||||
|
||||
locus7_ReferencesMap := make(map[string]string)
|
||||
locus7_ReferencesMap["SNPedia.com - rs4986850"] = "https://www.snpedia.com/index.php/Rs4986850"
|
||||
|
||||
locus7_RiskWeightsMap := make(map[string]int)
|
||||
locus7_RiskWeightsMap["C;C"] = 0
|
||||
locus7_RiskWeightsMap["T;C"] = 1
|
||||
locus7_RiskWeightsMap["C;T"] = 1
|
||||
locus7_RiskWeightsMap["T;T"] = 2
|
||||
|
||||
locus7_OddsRatiosMap := make(map[string]float64)
|
||||
locus7_OddsRatiosMap["C;C"] = 1
|
||||
locus7_OddsRatiosMap["T;C"] = 1.14
|
||||
locus7_OddsRatiosMap["C;T"] = 1.14
|
||||
locus7_OddsRatiosMap["T;T"] = 1.28
|
||||
|
||||
locus7_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus7_BasePairProbabilitiesMap["C;C"] = .92
|
||||
locus7_BasePairProbabilitiesMap["T;C"] = .07
|
||||
locus7_BasePairProbabilitiesMap["C;T"] = .07
|
||||
locus7_BasePairProbabilitiesMap["T;T"] = .01
|
||||
|
||||
locus7_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "d30087",
|
||||
LocusRSID: 4986850,
|
||||
RiskWeightsMap: locus7_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus7_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus7_BasePairProbabilitiesMap,
|
||||
References: locus7_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[4986850] = locus7_ReferencesMap
|
||||
|
||||
locus8_ReferencesMap := make(map[string]string)
|
||||
locus8_ReferencesMap["SNPedia.com - rs2227945"] = "https://www.snpedia.com/index.php/Rs2227945"
|
||||
|
||||
locus8_RiskWeightsMap := make(map[string]int)
|
||||
locus8_RiskWeightsMap["T;T"] = 0
|
||||
locus8_RiskWeightsMap["T;C"] = 1
|
||||
locus8_RiskWeightsMap["C;T"] = 1
|
||||
locus8_RiskWeightsMap["C;C"] = 2
|
||||
|
||||
locus8_OddsRatiosMap := make(map[string]float64)
|
||||
locus8_OddsRatiosMap["T;T"] = 1
|
||||
locus8_OddsRatiosMap["T;C"] = 1.14
|
||||
locus8_OddsRatiosMap["C;T"] = 1.14
|
||||
locus8_OddsRatiosMap["C;C"] = 1.28
|
||||
|
||||
locus8_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus8_BasePairProbabilitiesMap["T;T"] = .97
|
||||
locus8_BasePairProbabilitiesMap["T;C"] = .03
|
||||
locus8_BasePairProbabilitiesMap["C;T"] = .03
|
||||
locus8_BasePairProbabilitiesMap["C;C"] = .001
|
||||
|
||||
locus8_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "cafa72",
|
||||
LocusRSID: 2227945,
|
||||
RiskWeightsMap: locus8_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus8_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus8_BasePairProbabilitiesMap,
|
||||
References: locus8_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[2227945] = locus8_ReferencesMap
|
||||
|
||||
locus9_ReferencesMap := make(map[string]string)
|
||||
locus9_ReferencesMap["SNPedia.com - rs1799966"] = "https://www.snpedia.com/index.php/Rs1799966"
|
||||
|
||||
locus9_RiskWeightsMap := make(map[string]int)
|
||||
locus9_RiskWeightsMap["T;T"] = 0
|
||||
locus9_RiskWeightsMap["T;C"] = 1
|
||||
locus9_RiskWeightsMap["C;T"] = 1
|
||||
locus9_RiskWeightsMap["C;C"] = 2
|
||||
|
||||
locus9_OddsRatiosMap := make(map[string]float64)
|
||||
locus9_OddsRatiosMap["T;T"] = 1
|
||||
locus9_OddsRatiosMap["T;C"] = 1.14
|
||||
locus9_OddsRatiosMap["C;T"] = 1.14
|
||||
locus9_OddsRatiosMap["C;C"] = 1.28
|
||||
|
||||
locus9_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus9_BasePairProbabilitiesMap["T;T"] = .45
|
||||
locus9_BasePairProbabilitiesMap["T;C"] = .45
|
||||
locus9_BasePairProbabilitiesMap["C;T"] = .45
|
||||
locus9_BasePairProbabilitiesMap["C;C"] = .10
|
||||
|
||||
locus9_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "8f671c",
|
||||
LocusRSID: 1799966,
|
||||
RiskWeightsMap: locus9_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus9_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus9_BasePairProbabilitiesMap,
|
||||
References: locus9_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[1799966] = locus9_ReferencesMap
|
||||
|
||||
locus10_ReferencesMap := make(map[string]string)
|
||||
locus10_ReferencesMap["SNPedia.com - rs4987117"] = "https://www.snpedia.com/index.php/Rs4987117"
|
||||
|
||||
locus10_RiskWeightsMap := make(map[string]int)
|
||||
locus10_RiskWeightsMap["C;C"] = 0
|
||||
locus10_RiskWeightsMap["T;C"] = 1
|
||||
locus10_RiskWeightsMap["C;T"] = 1
|
||||
locus10_RiskWeightsMap["T;T"] = 2
|
||||
|
||||
locus10_OddsRatiosMap := make(map[string]float64)
|
||||
locus10_OddsRatiosMap["C;C"] = 1
|
||||
locus10_OddsRatiosMap["T;C"] = 1.14
|
||||
locus10_OddsRatiosMap["C;T"] = 1.14
|
||||
locus10_OddsRatiosMap["T;T"] = 1.28
|
||||
|
||||
locus10_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus10_BasePairProbabilitiesMap["C;C"] = .98
|
||||
locus10_BasePairProbabilitiesMap["T;C"] = .02
|
||||
locus10_BasePairProbabilitiesMap["C;T"] = .02
|
||||
locus10_BasePairProbabilitiesMap["T;T"] = .001
|
||||
|
||||
locus10_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "b3e49a",
|
||||
LocusRSID: 4987117,
|
||||
RiskWeightsMap: locus10_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus10_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus10_BasePairProbabilitiesMap,
|
||||
References: locus10_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[4987117] = locus10_ReferencesMap
|
||||
|
||||
locus11_ReferencesMap := make(map[string]string)
|
||||
locus11_ReferencesMap["SNPedia.com - rs1799954"] = "https://www.snpedia.com/index.php/Rs1799954"
|
||||
|
||||
locus11_RiskWeightsMap := make(map[string]int)
|
||||
locus11_RiskWeightsMap["C;C"] = 0
|
||||
locus11_RiskWeightsMap["T;C"] = 1
|
||||
locus11_RiskWeightsMap["C;T"] = 1
|
||||
locus11_RiskWeightsMap["T;T"] = 2
|
||||
|
||||
locus11_OddsRatiosMap := make(map[string]float64)
|
||||
locus11_OddsRatiosMap["C;C"] = 1
|
||||
locus11_OddsRatiosMap["T;C"] = 1.14
|
||||
locus11_OddsRatiosMap["C;T"] = 1.14
|
||||
locus11_OddsRatiosMap["T;T"] = 1.28
|
||||
|
||||
locus11_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus11_BasePairProbabilitiesMap["C;C"] = .97
|
||||
locus11_BasePairProbabilitiesMap["T;C"] = .03
|
||||
locus11_BasePairProbabilitiesMap["C;T"] = .03
|
||||
locus11_BasePairProbabilitiesMap["T;T"] = .001
|
||||
|
||||
locus11_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "8b0b02",
|
||||
LocusRSID: 1799954,
|
||||
RiskWeightsMap: locus11_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus11_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus11_BasePairProbabilitiesMap,
|
||||
References: locus11_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[1799954] = locus11_ReferencesMap
|
||||
|
||||
locus12_ReferencesMap := make(map[string]string)
|
||||
locus12_ReferencesMap["SNPedia.com - rs11571746"] = "https://www.snpedia.com/index.php/Rs11571746"
|
||||
|
||||
locus12_RiskWeightsMap := make(map[string]int)
|
||||
locus12_RiskWeightsMap["T;T"] = 0
|
||||
locus12_RiskWeightsMap["T;C"] = 1
|
||||
locus12_RiskWeightsMap["C;T"] = 1
|
||||
locus12_RiskWeightsMap["C;C"] = 2
|
||||
|
||||
locus12_OddsRatiosMap := make(map[string]float64)
|
||||
locus12_OddsRatiosMap["T;T"] = 1
|
||||
locus12_OddsRatiosMap["T;C"] = 1.14
|
||||
locus12_OddsRatiosMap["C;T"] = 1.14
|
||||
locus12_OddsRatiosMap["C;C"] = 1.28
|
||||
|
||||
locus12_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus12_BasePairProbabilitiesMap["T;T"] = .98
|
||||
locus12_BasePairProbabilitiesMap["T;C"] = .02
|
||||
locus12_BasePairProbabilitiesMap["C;T"] = .02
|
||||
locus12_BasePairProbabilitiesMap["C;C"] = .001
|
||||
|
||||
locus12_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "25cafc",
|
||||
LocusRSID: 11571746,
|
||||
RiskWeightsMap: locus12_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus12_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus12_BasePairProbabilitiesMap,
|
||||
References: locus12_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[11571746] = locus12_ReferencesMap
|
||||
|
||||
locus13_ReferencesMap := make(map[string]string)
|
||||
locus13_ReferencesMap["SNPedia.com - rs11571747"] = "https://www.snpedia.com/index.php/Rs11571747"
|
||||
|
||||
locus13_RiskWeightsMap := make(map[string]int)
|
||||
locus13_RiskWeightsMap["A;A"] = 0
|
||||
locus13_RiskWeightsMap["A;C"] = 1
|
||||
locus13_RiskWeightsMap["C;A"] = 1
|
||||
locus13_RiskWeightsMap["C;C"] = 2
|
||||
|
||||
locus13_OddsRatiosMap := make(map[string]float64)
|
||||
locus13_OddsRatiosMap["A;A"] = 1
|
||||
locus13_OddsRatiosMap["A;C"] = 1.14
|
||||
locus13_OddsRatiosMap["C;A"] = 1.14
|
||||
locus13_OddsRatiosMap["C;C"] = 1.28
|
||||
|
||||
locus13_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus13_BasePairProbabilitiesMap["A;A"] = .99
|
||||
locus13_BasePairProbabilitiesMap["A;C"] = .001
|
||||
locus13_BasePairProbabilitiesMap["C;A"] = .001
|
||||
locus13_BasePairProbabilitiesMap["C;C"] = .001
|
||||
|
||||
locus13_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "34c7e5",
|
||||
LocusRSID: 11571747,
|
||||
RiskWeightsMap: locus13_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus13_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus13_BasePairProbabilitiesMap,
|
||||
References: locus13_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[11571747] = locus13_ReferencesMap
|
||||
|
||||
locus14_ReferencesMap := make(map[string]string)
|
||||
locus14_ReferencesMap["SNPedia.com - rs4987047"] = "https://www.snpedia.com/index.php/Rs4987047"
|
||||
|
||||
locus14_RiskWeightsMap := make(map[string]int)
|
||||
locus14_RiskWeightsMap["A;A"] = 0
|
||||
locus14_RiskWeightsMap["A;T"] = 1
|
||||
locus14_RiskWeightsMap["T;A"] = 1
|
||||
locus14_RiskWeightsMap["T;T"] = 2
|
||||
|
||||
locus14_OddsRatiosMap := make(map[string]float64)
|
||||
locus14_OddsRatiosMap["A;A"] = 1
|
||||
locus14_OddsRatiosMap["A;T"] = 1.14
|
||||
locus14_OddsRatiosMap["T;A"] = 1.14
|
||||
locus14_OddsRatiosMap["T;T"] = 1.28
|
||||
|
||||
locus14_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus14_BasePairProbabilitiesMap["A;A"] = .94
|
||||
locus14_BasePairProbabilitiesMap["A;T"] = .94
|
||||
locus14_BasePairProbabilitiesMap["T;A"] = .05
|
||||
locus14_BasePairProbabilitiesMap["T;T"] = .01
|
||||
|
||||
locus14_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "60ce27",
|
||||
LocusRSID: 4987047,
|
||||
RiskWeightsMap: locus14_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus14_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus14_BasePairProbabilitiesMap,
|
||||
References: locus14_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[4987047] = locus14_ReferencesMap
|
||||
|
||||
locus15_ReferencesMap := make(map[string]string)
|
||||
locus15_ReferencesMap["SNPedia.com - rs11571833"] = "https://www.snpedia.com/index.php/Rs11571833"
|
||||
|
||||
locus15_RiskWeightsMap := make(map[string]int)
|
||||
locus15_RiskWeightsMap["A;A"] = 0
|
||||
locus15_RiskWeightsMap["T;A"] = 1
|
||||
locus15_RiskWeightsMap["A;T"] = 1
|
||||
locus15_RiskWeightsMap["T;T"] = 2
|
||||
|
||||
locus15_OddsRatiosMap := make(map[string]float64)
|
||||
locus15_OddsRatiosMap["A;A"] = 1
|
||||
locus15_OddsRatiosMap["T;A"] = 1.14
|
||||
locus15_OddsRatiosMap["A;T"] = 1.14
|
||||
locus15_OddsRatiosMap["T;T"] = 1.28
|
||||
|
||||
locus15_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus15_BasePairProbabilitiesMap["A;A"] = .99
|
||||
locus15_BasePairProbabilitiesMap["T;A"] = .01
|
||||
locus15_BasePairProbabilitiesMap["A;T"] = .01
|
||||
locus15_BasePairProbabilitiesMap["T;T"] = .001
|
||||
|
||||
locus15_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "328cdf",
|
||||
LocusRSID: 11571833,
|
||||
RiskWeightsMap: locus15_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus15_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus15_BasePairProbabilitiesMap,
|
||||
References: locus15_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[11571833] = locus15_ReferencesMap
|
||||
|
||||
locus16_ReferencesMap := make(map[string]string)
|
||||
locus16_ReferencesMap["SNPedia.com - rs1801426"] = "https://www.snpedia.com/index.php/Rs1801426"
|
||||
|
||||
locus16_RiskWeightsMap := make(map[string]int)
|
||||
locus16_RiskWeightsMap["A;A"] = 0
|
||||
locus16_RiskWeightsMap["G;A"] = 1
|
||||
locus16_RiskWeightsMap["A;G"] = 1
|
||||
locus16_RiskWeightsMap["G;G"] = 2
|
||||
|
||||
locus16_OddsRatiosMap := make(map[string]float64)
|
||||
locus16_OddsRatiosMap["A;A"] = 1
|
||||
locus16_OddsRatiosMap["G;A"] = 1.14
|
||||
locus16_OddsRatiosMap["A;G"] = 1.14
|
||||
locus16_OddsRatiosMap["G;G"] = 1.28
|
||||
|
||||
locus16_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus16_BasePairProbabilitiesMap["A;A"] = .90
|
||||
locus16_BasePairProbabilitiesMap["G;A"] = .09
|
||||
locus16_BasePairProbabilitiesMap["A;G"] = .09
|
||||
locus16_BasePairProbabilitiesMap["G;G"] = .01
|
||||
|
||||
locus16_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "849bc7",
|
||||
LocusRSID: 1801426,
|
||||
RiskWeightsMap: locus16_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus16_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus16_BasePairProbabilitiesMap,
|
||||
References: locus16_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[1801426] = locus16_ReferencesMap
|
||||
|
||||
locus17_ReferencesMap := make(map[string]string)
|
||||
locus17_ReferencesMap["SNPedia.com - rs3218707"] = "https://www.snpedia.com/index.php/Rs3218707"
|
||||
|
||||
locus17_RiskWeightsMap := make(map[string]int)
|
||||
locus17_RiskWeightsMap["G;G"] = 0
|
||||
locus17_RiskWeightsMap["G;C"] = 1
|
||||
locus17_RiskWeightsMap["C;G"] = 1
|
||||
locus17_RiskWeightsMap["C;C"] = 2
|
||||
|
||||
locus17_OddsRatiosMap := make(map[string]float64)
|
||||
locus17_OddsRatiosMap["G;G"] = 1
|
||||
locus17_OddsRatiosMap["G;C"] = 1.14
|
||||
locus17_OddsRatiosMap["C;G"] = 1.14
|
||||
locus17_OddsRatiosMap["C;C"] = 1.28
|
||||
|
||||
locus17_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus17_BasePairProbabilitiesMap["G;G"] = .96
|
||||
locus17_BasePairProbabilitiesMap["G;C"] = .04
|
||||
locus17_BasePairProbabilitiesMap["C;G"] = .04
|
||||
locus17_BasePairProbabilitiesMap["C;C"] = .001
|
||||
|
||||
locus17_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "5af5e3",
|
||||
LocusRSID: 3218707,
|
||||
RiskWeightsMap: locus17_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus17_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus17_BasePairProbabilitiesMap,
|
||||
References: locus17_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[3218707] = locus17_ReferencesMap
|
||||
|
||||
locus18_ReferencesMap := make(map[string]string)
|
||||
locus18_ReferencesMap["SNPedia.com - rs4987945"] = "https://www.snpedia.com/index.php/Rs4987945"
|
||||
|
||||
locus18_RiskWeightsMap := make(map[string]int)
|
||||
locus18_RiskWeightsMap["C;C"] = 0
|
||||
locus18_RiskWeightsMap["C;G"] = 1
|
||||
locus18_RiskWeightsMap["G;C"] = 1
|
||||
locus18_RiskWeightsMap["G;G"] = 2
|
||||
|
||||
locus18_OddsRatiosMap := make(map[string]float64)
|
||||
locus18_OddsRatiosMap["C;C"] = 1
|
||||
locus18_OddsRatiosMap["C;G"] = 1.14
|
||||
locus18_OddsRatiosMap["G;C"] = 1.14
|
||||
locus18_OddsRatiosMap["G;G"] = 1.28
|
||||
|
||||
locus18_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus18_BasePairProbabilitiesMap["C;C"] = .95
|
||||
locus18_BasePairProbabilitiesMap["C;G"] = .04
|
||||
locus18_BasePairProbabilitiesMap["G;C"] = .04
|
||||
locus18_BasePairProbabilitiesMap["G;G"] = .01
|
||||
|
||||
locus18_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "c354fa",
|
||||
LocusRSID: 4987945,
|
||||
RiskWeightsMap: locus18_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus18_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus18_BasePairProbabilitiesMap,
|
||||
References: locus18_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[4987945] = locus18_ReferencesMap
|
||||
|
||||
locus19_ReferencesMap := make(map[string]string)
|
||||
locus19_ReferencesMap["SNPedia.com - rs4986761"] = "https://www.snpedia.com/index.php/Rs4986761"
|
||||
|
||||
locus19_RiskWeightsMap := make(map[string]int)
|
||||
locus19_RiskWeightsMap["T;T"] = 0
|
||||
locus19_RiskWeightsMap["C;T"] = 1
|
||||
locus19_RiskWeightsMap["T;C"] = 1
|
||||
locus19_RiskWeightsMap["C;C"] = 2
|
||||
|
||||
locus19_OddsRatiosMap := make(map[string]float64)
|
||||
locus19_OddsRatiosMap["T;T"] = 1
|
||||
locus19_OddsRatiosMap["C;T"] = 1.05
|
||||
locus19_OddsRatiosMap["T;C"] = 1.05
|
||||
locus19_OddsRatiosMap["C;C"] = 1.51
|
||||
|
||||
locus19_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus19_BasePairProbabilitiesMap["T;T"] = .99
|
||||
locus19_BasePairProbabilitiesMap["C;T"] = .01
|
||||
locus19_BasePairProbabilitiesMap["T;C"] = .01
|
||||
locus19_BasePairProbabilitiesMap["C;C"] = .001
|
||||
|
||||
locus19_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "eedc23",
|
||||
LocusRSID: 4986761,
|
||||
RiskWeightsMap: locus19_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus19_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus19_BasePairProbabilitiesMap,
|
||||
References: locus19_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[4986761] = locus19_ReferencesMap
|
||||
|
||||
locus20_ReferencesMap := make(map[string]string)
|
||||
locus20_ReferencesMap["SNPedia.com - rs3218695"] = "https://www.snpedia.com/index.php/Rs3218695"
|
||||
|
||||
locus20_RiskWeightsMap := make(map[string]int)
|
||||
locus20_RiskWeightsMap["C;C"] = 0
|
||||
locus20_RiskWeightsMap["C;A"] = 1
|
||||
locus20_RiskWeightsMap["A;C"] = 1
|
||||
locus20_RiskWeightsMap["A;A"] = 2
|
||||
|
||||
locus20_OddsRatiosMap := make(map[string]float64)
|
||||
locus20_OddsRatiosMap["C;C"] = 1
|
||||
locus20_OddsRatiosMap["C;A"] = 1.14
|
||||
locus20_OddsRatiosMap["A;C"] = 1.14
|
||||
locus20_OddsRatiosMap["A;A"] = 1.28
|
||||
|
||||
locus20_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus20_BasePairProbabilitiesMap["C;C"] = .98
|
||||
locus20_BasePairProbabilitiesMap["C;A"] = .02
|
||||
locus20_BasePairProbabilitiesMap["A;C"] = .02
|
||||
locus20_BasePairProbabilitiesMap["A;A"] = .001
|
||||
|
||||
locus20_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "2ee027",
|
||||
LocusRSID: 3218695,
|
||||
RiskWeightsMap: locus20_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus20_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus20_BasePairProbabilitiesMap,
|
||||
References: locus20_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[3218695] = locus20_ReferencesMap
|
||||
|
||||
locus21_ReferencesMap := make(map[string]string)
|
||||
locus21_ReferencesMap["SNPedia.com - rs1800056"] = "https://www.snpedia.com/index.php/Rs1800056"
|
||||
|
||||
locus21_RiskWeightsMap := make(map[string]int)
|
||||
locus21_RiskWeightsMap["T;T"] = 0
|
||||
locus21_RiskWeightsMap["C;T"] = 1
|
||||
locus21_RiskWeightsMap["T;C"] = 1
|
||||
locus21_RiskWeightsMap["C;C"] = 2
|
||||
|
||||
locus21_OddsRatiosMap := make(map[string]float64)
|
||||
locus21_OddsRatiosMap["T;T"] = 1
|
||||
locus21_OddsRatiosMap["C;T"] = 1.05
|
||||
locus21_OddsRatiosMap["T;C"] = 1.05
|
||||
locus21_OddsRatiosMap["C;C"] = 1.51
|
||||
|
||||
locus21_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus21_BasePairProbabilitiesMap["T;T"] = .97
|
||||
locus21_BasePairProbabilitiesMap["C;T"] = .03
|
||||
locus21_BasePairProbabilitiesMap["T;C"] = .03
|
||||
locus21_BasePairProbabilitiesMap["C;C"] = .001
|
||||
|
||||
locus21_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "fc4bab",
|
||||
LocusRSID: 1800056,
|
||||
RiskWeightsMap: locus21_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus21_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus21_BasePairProbabilitiesMap,
|
||||
References: locus21_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[1800056] = locus21_ReferencesMap
|
||||
|
||||
locus22_ReferencesMap := make(map[string]string)
|
||||
locus22_ReferencesMap["SNPedia.com - rs1800057"] = "https://www.snpedia.com/index.php/Rs1800057"
|
||||
|
||||
locus22_RiskWeightsMap := make(map[string]int)
|
||||
locus22_RiskWeightsMap["C;C"] = 0
|
||||
locus22_RiskWeightsMap["C;G"] = 1
|
||||
locus22_RiskWeightsMap["G;C"] = 1
|
||||
locus22_RiskWeightsMap["G;G"] = 2
|
||||
|
||||
locus22_OddsRatiosMap := make(map[string]float64)
|
||||
locus22_OddsRatiosMap["C;C"] = 1
|
||||
locus22_OddsRatiosMap["C;G"] = 1.05
|
||||
locus22_OddsRatiosMap["G;C"] = 1.05
|
||||
locus22_OddsRatiosMap["G;G"] = 1.51
|
||||
|
||||
locus22_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus22_BasePairProbabilitiesMap["C;C"] = .97
|
||||
locus22_BasePairProbabilitiesMap["C;G"] = .03
|
||||
locus22_BasePairProbabilitiesMap["G;C"] = .03
|
||||
locus22_BasePairProbabilitiesMap["G;G"] = .001
|
||||
|
||||
locus22_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "f8b225",
|
||||
LocusRSID: 1800057,
|
||||
RiskWeightsMap: locus22_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus22_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus22_BasePairProbabilitiesMap,
|
||||
References: locus22_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[1800057] = locus22_ReferencesMap
|
||||
|
||||
locus23_ReferencesMap := make(map[string]string)
|
||||
locus23_ReferencesMap["SNPedia.com - rs3092856"] = "https://www.snpedia.com/index.php/Rs3092856"
|
||||
|
||||
locus23_RiskWeightsMap := make(map[string]int)
|
||||
locus23_RiskWeightsMap["C;C"] = 0
|
||||
locus23_RiskWeightsMap["C;T"] = 1
|
||||
locus23_RiskWeightsMap["T;C"] = 1
|
||||
locus23_RiskWeightsMap["T;T"] = 2
|
||||
|
||||
locus23_OddsRatiosMap := make(map[string]float64)
|
||||
locus23_OddsRatiosMap["C;C"] = 1
|
||||
locus23_OddsRatiosMap["C;T"] = 1.14
|
||||
locus23_OddsRatiosMap["T;C"] = 1.14
|
||||
locus23_OddsRatiosMap["T;T"] = 1.28
|
||||
|
||||
locus23_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus23_BasePairProbabilitiesMap["C;C"] = .95
|
||||
locus23_BasePairProbabilitiesMap["C;T"] = .05
|
||||
locus23_BasePairProbabilitiesMap["T;C"] = .05
|
||||
locus23_BasePairProbabilitiesMap["T;T"] = .001
|
||||
|
||||
locus23_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "4a072c",
|
||||
LocusRSID: 3092856,
|
||||
RiskWeightsMap: locus23_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus23_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus23_BasePairProbabilitiesMap,
|
||||
References: locus23_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[3092856] = locus23_ReferencesMap
|
||||
|
||||
locus24_ReferencesMap := make(map[string]string)
|
||||
locus24_ReferencesMap["SNPedia.com - rs1800058"] = "https://www.snpedia.com/index.php/Rs1800058"
|
||||
|
||||
locus24_RiskWeightsMap := make(map[string]int)
|
||||
locus24_RiskWeightsMap["C;C"] = 0
|
||||
locus24_RiskWeightsMap["C;T"] = 1
|
||||
locus24_RiskWeightsMap["T;C"] = 1
|
||||
locus24_RiskWeightsMap["T;T"] = 2
|
||||
|
||||
locus24_OddsRatiosMap := make(map[string]float64)
|
||||
locus24_OddsRatiosMap["C;C"] = 1
|
||||
locus24_OddsRatiosMap["C;T"] = 1.05
|
||||
locus24_OddsRatiosMap["T;C"] = 1.05
|
||||
locus24_OddsRatiosMap["T;T"] = 1.51
|
||||
|
||||
locus24_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus24_BasePairProbabilitiesMap["C;C"] = .95
|
||||
locus24_BasePairProbabilitiesMap["C;T"] = .04
|
||||
locus24_BasePairProbabilitiesMap["T;C"] = .04
|
||||
locus24_BasePairProbabilitiesMap["T;T"] = .01
|
||||
|
||||
locus24_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "070f24",
|
||||
LocusRSID: 1800058,
|
||||
RiskWeightsMap: locus24_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus24_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus24_BasePairProbabilitiesMap,
|
||||
References: locus24_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[1800058] = locus24_ReferencesMap
|
||||
|
||||
locus25_ReferencesMap := make(map[string]string)
|
||||
locus25_ReferencesMap["SNPedia.com - rs1801673"] = "https://www.snpedia.com/index.php/Rs1801673"
|
||||
|
||||
locus25_RiskWeightsMap := make(map[string]int)
|
||||
locus25_RiskWeightsMap["A;A"] = 0
|
||||
locus25_RiskWeightsMap["A;T"] = 1
|
||||
locus25_RiskWeightsMap["T;A"] = 1
|
||||
locus25_RiskWeightsMap["T;T"] = 2
|
||||
|
||||
locus25_OddsRatiosMap := make(map[string]float64)
|
||||
locus25_OddsRatiosMap["A;A"] = 1
|
||||
locus25_OddsRatiosMap["A;T"] = 1.14
|
||||
locus25_OddsRatiosMap["T;A"] = 1.14
|
||||
locus25_OddsRatiosMap["T;T"] = 1.28
|
||||
|
||||
locus25_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus25_BasePairProbabilitiesMap["A;A"] = .99
|
||||
locus25_BasePairProbabilitiesMap["A;T"] = .01
|
||||
locus25_BasePairProbabilitiesMap["T;A"] = .01
|
||||
locus25_BasePairProbabilitiesMap["T;T"] = .001
|
||||
|
||||
locus25_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "d08516",
|
||||
LocusRSID: 1801673,
|
||||
RiskWeightsMap: locus25_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus25_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus25_BasePairProbabilitiesMap,
|
||||
References: locus25_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[1801673] = locus25_ReferencesMap
|
||||
|
||||
locus26_ReferencesMap := make(map[string]string)
|
||||
locus26_ReferencesMap["SNPedia.com - rs17879961"] = "https://www.snpedia.com/index.php/Rs17879961"
|
||||
|
||||
locus26_RiskWeightsMap := make(map[string]int)
|
||||
locus26_RiskWeightsMap["A;A"] = 0
|
||||
locus26_RiskWeightsMap["A;G"] = 1
|
||||
locus26_RiskWeightsMap["G;A"] = 1
|
||||
locus26_RiskWeightsMap["G;G"] = 2
|
||||
|
||||
locus26_OddsRatiosMap := make(map[string]float64)
|
||||
locus26_OddsRatiosMap["A;A"] = 1
|
||||
locus26_OddsRatiosMap["A;G"] = 1.14
|
||||
locus26_OddsRatiosMap["G;A"] = 1.14
|
||||
locus26_OddsRatiosMap["G;G"] = 1.28
|
||||
|
||||
locus26_BasePairProbabilitiesMap := make(map[string]float64)
|
||||
locus26_BasePairProbabilitiesMap["A;A"] = .98
|
||||
locus26_BasePairProbabilitiesMap["A;G"] = .02
|
||||
locus26_BasePairProbabilitiesMap["G;A"] = .02
|
||||
locus26_BasePairProbabilitiesMap["G;G"] = .001
|
||||
|
||||
locus26_Object := DiseaseLocus{
|
||||
|
||||
LocusIdentifier: "047b84",
|
||||
LocusRSID: 17879961,
|
||||
RiskWeightsMap: locus26_RiskWeightsMap,
|
||||
MinimumRiskWeight: 0,
|
||||
MaximumRiskWeight: 2,
|
||||
OddsRatiosMap: locus26_OddsRatiosMap,
|
||||
BasePairProbabilitiesMap: locus26_BasePairProbabilitiesMap,
|
||||
References: locus26_ReferencesMap,
|
||||
}
|
||||
locusReferencesMap[17879961] = locus26_ReferencesMap
|
||||
|
||||
// TODO:
|
||||
//-https://www.snpedia.com/index.php/Rs1042522
|
||||
|
@ -883,7 +163,7 @@ func getBreastCancerDiseaseObject()PolygenicDisease{
|
|||
//-https://www.snpedia.com/index.php/Rs7895676
|
||||
//-https://www.snpedia.com/index.php/Rs140068132
|
||||
|
||||
breastCancerLociList := []DiseaseLocus{locus1_Object, locus2_Object, locus3_Object, locus4_Object, locus5_Object, locus6_Object, locus7_Object, locus8_Object, locus9_Object, locus10_Object, locus11_Object, locus12_Object, locus13_Object, locus14_Object, locus15_Object, locus16_Object, locus17_Object, locus18_Object, locus19_Object, locus20_Object, locus21_Object, locus22_Object, locus23_Object, locus24_Object, locus25_Object, locus26_Object}
|
||||
breastCancerLociList := helpers.GetListOfMapKeys(locusReferencesMap)
|
||||
|
||||
referencesMap := make(map[string]string)
|
||||
referencesMap["SNPedia.com - Breast Cancer"] = "https://www.snpedia.com/index.php/Breast_cancer"
|
||||
|
@ -948,6 +228,7 @@ func getBreastCancerDiseaseObject()PolygenicDisease{
|
|||
DiseaseName: "Breast Cancer",
|
||||
EffectedSex: "Both",
|
||||
DiseaseDescription: "Cancer growth in the tissue of a person's chest breast.",
|
||||
LocusReferencesMap: locusReferencesMap,
|
||||
LociList: breastCancerLociList,
|
||||
GetAverageRiskProbabilitiesFunction: getAverageRiskProbabilitiesFunction,
|
||||
References: referencesMap,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
// polygenicDiseases provides information about polygenic diseases and the SNP base changes that effect a person's risk of becoming victim to them.
|
||||
// polygenicDiseases provides information about polygenic diseases and the loci that influence them
|
||||
|
||||
package polygenicDiseases
|
||||
|
||||
|
@ -8,42 +8,8 @@ package polygenicDiseases
|
|||
// Polygenic disease probabilities are less accurate, because individual base pair changes only cause comparatively small changes in the disease risk.
|
||||
// Polygenic diseases are also more influenced by environmental factors, further decreasing risk accuracy.
|
||||
|
||||
//TODO: Eventually we want to use neural networks for polygenic disease prediction.
|
||||
// This package is currently a less accurate solution until we get access to the necessary training data.
|
||||
|
||||
import "errors"
|
||||
|
||||
// DiseaseLocus is a location on a human genome that has an effect on the disease
|
||||
type DiseaseLocus struct{
|
||||
|
||||
// 3 byte identifier, encoded in Hex.
|
||||
LocusIdentifier string
|
||||
|
||||
// RSID that represents this locus
|
||||
// If multiple RSIDs represent the same locus, use the first rsID for the locus in the locusMetadata package
|
||||
LocusRSID int64
|
||||
|
||||
// Map Structure: Base pair -> Effect weight (Positive number = increased risk, negative number = decreased risk)
|
||||
// The number only indicates a general effect of the base, for bases for which we do not have risk probability statistics
|
||||
// 0 indicates that the base has no effect
|
||||
RiskWeightsMap map[string]int
|
||||
|
||||
// Minimum and maximum values in above map
|
||||
MinimumRiskWeight int
|
||||
MaximumRiskWeight int
|
||||
|
||||
// Map Structure: Base Pair -> Odds ratio of BasePair/Normal (common) Base pair
|
||||
// Number is greater than 1 = Increases risk, Number is less than 1 = decreases risk
|
||||
// 1 indicates that the base has no impact
|
||||
OddsRatiosMap map[string]float64
|
||||
|
||||
// Map Structure: Base Pair -> Probability that a person will have that base pair for the general population
|
||||
BasePairProbabilitiesMap map[string]float64
|
||||
|
||||
// Map Structure: Reference name -> Reference link
|
||||
References map[string]string
|
||||
}
|
||||
|
||||
|
||||
type PolygenicDisease struct{
|
||||
|
||||
|
@ -54,7 +20,14 @@ type PolygenicDisease struct{
|
|||
// Is either "Mate"/"Female"/"Both"
|
||||
EffectedSex string
|
||||
|
||||
LociList []DiseaseLocus
|
||||
// This is a list of rsIDs which are known to have an effect on this disease
|
||||
// We use these loci to predict trait outcomes with neural networks.
|
||||
// Map Structure: rsID -> (map[Reference Name]Reference Link)
|
||||
LocusReferencesMap map[int64]map[string]string
|
||||
|
||||
// This is a list of all loci used to predict this disease's risk
|
||||
// This should be a list of the keys in LocusReferencesMap
|
||||
LociList []int64
|
||||
|
||||
// Inputs:
|
||||
// -string: "Mate"/"Female"
|
||||
|
@ -64,10 +37,12 @@ type PolygenicDisease struct{
|
|||
// -error
|
||||
GetAverageRiskProbabilitiesFunction func(string, int)(float64, error)
|
||||
|
||||
// This map contains scientific resources about this disease
|
||||
// Map Structure: Reference name -> Reference link
|
||||
References map[string]string
|
||||
}
|
||||
|
||||
|
||||
var polygenicDiseaseNamesList []string
|
||||
var polygenicDiseaseObjectsList []PolygenicDisease
|
||||
|
||||
|
@ -75,8 +50,9 @@ var polygenicDiseaseObjectsList []PolygenicDisease
|
|||
func InitializePolygenicDiseaseVariables(){
|
||||
|
||||
breastCancerObject := getBreastCancerDiseaseObject()
|
||||
autismObject := getAutismDiseaseObject()
|
||||
|
||||
polygenicDiseaseObjectsList = []PolygenicDisease{breastCancerObject}
|
||||
polygenicDiseaseObjectsList = []PolygenicDisease{breastCancerObject, autismObject}
|
||||
|
||||
polygenicDiseaseNamesList = make([]string, 0, len(polygenicDiseaseObjectsList))
|
||||
|
||||
|
@ -94,7 +70,7 @@ func InitializePolygenicDiseaseVariables(){
|
|||
func GetPolygenicDiseaseNamesList()([]string, error){
|
||||
|
||||
if (polygenicDiseaseNamesList == nil){
|
||||
return nil, errors.New("GetDiseaseNamesList called when list is not initialized.")
|
||||
return nil, errors.New("GetPolygenicDiseaseNamesList called when list is not initialized.")
|
||||
}
|
||||
|
||||
return polygenicDiseaseNamesList, nil
|
||||
|
@ -127,40 +103,3 @@ func GetPolygenicDiseaseObject(diseaseName string)(PolygenicDisease, error){
|
|||
return PolygenicDisease{}, errors.New("GetPolygenicDiseaseObject called with unknown disease name: " + diseaseName)
|
||||
}
|
||||
|
||||
|
||||
//Outputs:
|
||||
// -map[string]DiseaseLocus: Map of LocusIdentifier -> LocusObject
|
||||
// -error (will return err if diseaseName is not found)
|
||||
func GetPolygenicDiseaseLociMap(diseaseName string)(map[string]DiseaseLocus, error){
|
||||
|
||||
diseaseObject, err := GetPolygenicDiseaseObject(diseaseName)
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
diseaseLociList := diseaseObject.LociList
|
||||
|
||||
diseaseLociMap := make(map[string]DiseaseLocus)
|
||||
|
||||
for _, locusObject := range diseaseLociList{
|
||||
|
||||
locusIdentifier := locusObject.LocusIdentifier
|
||||
diseaseLociMap[locusIdentifier] = locusObject
|
||||
}
|
||||
|
||||
return diseaseLociMap, nil
|
||||
}
|
||||
|
||||
func GetPolygenicDiseaseLocusObject(diseaseName string, locusIdentifier string)(DiseaseLocus, error){
|
||||
|
||||
diseaseLociMap, err := GetPolygenicDiseaseLociMap(diseaseName)
|
||||
if (err != nil){ return DiseaseLocus{}, err }
|
||||
|
||||
locusObject, exists := diseaseLociMap[locusIdentifier]
|
||||
if (exists == false){
|
||||
return DiseaseLocus{}, errors.New("GetDiseaseLocusObject called with unknown locus identifier: " + locusIdentifier)
|
||||
}
|
||||
|
||||
return locusObject, nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -164,6 +164,7 @@ func getEyeColorTraitObject()Trait{
|
|||
LociList_Rules: []int64{},
|
||||
RulesList: []TraitRule{},
|
||||
OutcomesList: []string{"Blue", "Green", "Hazel", "Brown"},
|
||||
NumericValueFormatter: nil,
|
||||
ReferencesMap: referencesMap,
|
||||
}
|
||||
|
||||
|
|
|
@ -142,6 +142,7 @@ func getFacialStructureTraitObject()Trait{
|
|||
LociList_Rules: []int64{},
|
||||
RulesList: []TraitRule{},
|
||||
OutcomesList: []string{},
|
||||
NumericValueFormatter: nil,
|
||||
ReferencesMap: referencesMap,
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ func getHairColorTraitObject()Trait{
|
|||
LociList_Rules: []int64{},
|
||||
RulesList: []TraitRule{},
|
||||
OutcomesList: []string{},
|
||||
NumericValueFormatter: nil,
|
||||
ReferencesMap: referencesMap,
|
||||
}
|
||||
|
||||
|
|
|
@ -245,6 +245,7 @@ func getHairTextureTraitObject()Trait{
|
|||
LociList_Rules: lociList_Rules,
|
||||
RulesList: hairTextureRulesList,
|
||||
OutcomesList: outcomesList,
|
||||
NumericValueFormatter: nil,
|
||||
ReferencesMap: referencesMap,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package traits
|
||||
|
||||
import "seekia/internal/globalSettings"
|
||||
import "seekia/internal/helpers"
|
||||
|
||||
import "maps"
|
||||
|
||||
import _ "embed"
|
||||
|
||||
import "errors"
|
||||
import "encoding/gob"
|
||||
import "bytes"
|
||||
|
||||
|
@ -50,6 +52,40 @@ func getHeightTraitObject()(Trait, error){
|
|||
referencesMap := make(map[string]string)
|
||||
referencesMap["GIANT consortium - Meta-analyses of Genome-Wide Association Studies - 2022 - Height"] = "https://portals.broadinstitute.org/collaboration/giant/index.php/GIANT_consortium_data_files"
|
||||
|
||||
numericValueFormatter := func(inputHeight float64, _ bool)(string, error){
|
||||
|
||||
getMyMetricOrImperial := func()(string, error){
|
||||
|
||||
exists, metricOrImperial, err := globalSettings.GetSetting("MetricOrImperial")
|
||||
if (err != nil) { return "", err }
|
||||
if (exists == false){
|
||||
return "Metric", nil
|
||||
}
|
||||
if (metricOrImperial != "Metric" && metricOrImperial != "Imperial"){
|
||||
return "", errors.New("Malformed globalSettings: Invalid metricOrImperial: " + metricOrImperial)
|
||||
}
|
||||
|
||||
return metricOrImperial, nil
|
||||
}
|
||||
|
||||
myMetricOrImperial, err := getMyMetricOrImperial()
|
||||
if (err != nil){ return "", err }
|
||||
if (myMetricOrImperial == "Metric"){
|
||||
centimetersString := helpers.ConvertFloat64ToStringRounded(inputHeight, 2)
|
||||
|
||||
//TODO: Translate units
|
||||
|
||||
centimetersWithUnits := centimetersString + " centimeters"
|
||||
|
||||
return centimetersWithUnits, nil
|
||||
}
|
||||
|
||||
feetInchesString, err := helpers.ConvertCentimetersToFeetInchesTranslatedString(inputHeight)
|
||||
if (err != nil) { return "", err }
|
||||
|
||||
return feetInchesString, nil
|
||||
}
|
||||
|
||||
heightObject := Trait{
|
||||
TraitName: "Height",
|
||||
TraitDescription: "The distance between the top of a standing person head and the floor.",
|
||||
|
@ -59,6 +95,7 @@ func getHeightTraitObject()(Trait, error){
|
|||
LociList_Rules: []int64{},
|
||||
RulesList: []TraitRule{},
|
||||
OutcomesList: []string{},
|
||||
NumericValueFormatter: numericValueFormatter,
|
||||
ReferencesMap: referencesMap,
|
||||
}
|
||||
|
||||
|
|
59
resources/geneticReferences/traits/homosexualness.go
Normal file
59
resources/geneticReferences/traits/homosexualness.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package traits
|
||||
|
||||
import "seekia/internal/helpers"
|
||||
|
||||
import "maps"
|
||||
|
||||
func getHomosexualnessTraitObject()Trait{
|
||||
|
||||
// Map Structure: rsID -> References Map
|
||||
locusReferencesMap := make(map[int64]map[string]string)
|
||||
|
||||
referencesMap_List1 := make(map[string]string)
|
||||
referencesMap_List1["Large-scale GWAS reveals insights into the genetic architecture of same-sex sexual behavior"] = "https://www.science.org/doi/10.1126/science.aat7693"
|
||||
|
||||
lociList_1 := []int64{
|
||||
10261857,
|
||||
28371400,
|
||||
34730029,
|
||||
11114975,
|
||||
}
|
||||
|
||||
for _, rsID := range lociList_1{
|
||||
locusReferencesMap[rsID] = maps.Clone(referencesMap_List1)
|
||||
}
|
||||
|
||||
homosexualnessLociList := helpers.GetListOfMapKeys(locusReferencesMap)
|
||||
|
||||
referencesMap := make(map[string]string)
|
||||
referencesMap["Large-scale GWAS reveals insights into the genetic architecture of same-sex sexual behavior"] = "https://www.science.org/doi/10.1126/science.aat7693"
|
||||
|
||||
valueFormatter := func(inputHomosexualness float64, showUnits bool)(string, error){
|
||||
|
||||
inputHomosexualnessString := helpers.ConvertIntToString(int(inputHomosexualness))
|
||||
|
||||
if (showUnits == false){
|
||||
return inputHomosexualnessString, nil
|
||||
}
|
||||
|
||||
formattedValue := inputHomosexualnessString + "/10"
|
||||
|
||||
return formattedValue, nil
|
||||
}
|
||||
|
||||
homosexualnessObject := Trait{
|
||||
TraitName: "Homosexualness",
|
||||
TraitDescription: "Feelings of sexual attraction towards people who belong to a person's own sex.",
|
||||
DiscreteOrNumeric: "Numeric",
|
||||
LocusReferencesMap: locusReferencesMap,
|
||||
LociList: homosexualnessLociList,
|
||||
LociList_Rules: []int64{},
|
||||
RulesList: []TraitRule{},
|
||||
OutcomesList: []string{},
|
||||
NumericValueFormatter: valueFormatter,
|
||||
ReferencesMap: referencesMap,
|
||||
}
|
||||
|
||||
return homosexualnessObject
|
||||
}
|
||||
|
|
@ -140,6 +140,7 @@ func getLactoseToleranceTraitObject()Trait{
|
|||
LociList_Rules: lociList_Rules,
|
||||
RulesList: lactoseToleranceRulesList,
|
||||
OutcomesList: outcomesList,
|
||||
NumericValueFormatter: nil,
|
||||
ReferencesMap: referencesMap,
|
||||
}
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ func getSkinColorTraitObject()Trait{
|
|||
LociList_Rules: []int64{},
|
||||
RulesList: []TraitRule{},
|
||||
OutcomesList: []string{},
|
||||
NumericValueFormatter: nil,
|
||||
ReferencesMap: referencesMap,
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,17 @@ type Trait struct{
|
|||
// If the trait is Numeric, or their or no rules nor a neural network, then this list will be empty.
|
||||
OutcomesList []string
|
||||
|
||||
// This function returns a formatted, translated representation of a numeric value for this trait
|
||||
// For example, "150 centimeters", "5 foot 10 inches", "4/10"
|
||||
// Inputs:
|
||||
// -float64: The value to format
|
||||
// -bool: Show "/10" units
|
||||
// -The "/10" units are used for certain traits, where the unit value is not a real-world measurement (such as length, weight, etc.)
|
||||
// -An example of an "/10" trait is Homosexuality, which is represented by a value between 0 and 10.
|
||||
// -We don't want to "/10" if we are displaying a confidence range (Example: +/- 5.2)
|
||||
// -If we did, then people would get confused by thinking the unit represents a fraction
|
||||
NumericValueFormatter func(float64, bool)(string, error)
|
||||
|
||||
// This map contains scientific resources about this trait
|
||||
// Map structure: Reference name -> Reference link
|
||||
ReferencesMap map[string]string
|
||||
|
@ -99,11 +110,13 @@ func InitializeTraitVariables()error{
|
|||
eyeColorObject := getEyeColorTraitObject()
|
||||
hairColorObject := getHairColorTraitObject()
|
||||
skinColorObject := getSkinColorTraitObject()
|
||||
homosexualnessObject := getHomosexualnessTraitObject()
|
||||
|
||||
heightObject, err := getHeightTraitObject()
|
||||
if (err != nil){ return err }
|
||||
|
||||
traitObjectsList = []Trait{lactoseToleranceObject, hairTextureObject, facialStructureObject, eyeColorObject, hairColorObject, skinColorObject, heightObject}
|
||||
|
||||
traitObjectsList = []Trait{lactoseToleranceObject, hairTextureObject, facialStructureObject, eyeColorObject, hairColorObject, skinColorObject, heightObject, homosexualnessObject}
|
||||
|
||||
traitNamesList = make([]string, 0, len(traitObjectsList))
|
||||
locusRSIDsMap = make(map[string]int64)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
// createGeneticModels.go provides an interface to create genetic prediction models
|
||||
// These are neural networks which predict traits such as eye color from raw genome files
|
||||
// These are neural networks which predict attributes such as eye color and autism from raw genome files
|
||||
// The OpenSNP.org dataset is used, and more datasets will be added in the future.
|
||||
// You must download the dataset and extract it. The instructions are described in the utility.
|
||||
// The trained models are saved in the /resources/geneticPredictionModels package for use in the Seekia app.
|
||||
|
@ -16,6 +16,7 @@ import "fyne.io/fyne/v2/layout"
|
|||
import "fyne.io/fyne/v2/dialog"
|
||||
import "fyne.io/fyne/v2/data/binding"
|
||||
|
||||
import "seekia/resources/geneticReferences/polygenicDiseases"
|
||||
import "seekia/resources/geneticReferences/traits"
|
||||
import "seekia/resources/geneticReferences/locusMetadata"
|
||||
|
||||
|
@ -24,6 +25,7 @@ import "seekia/internal/genetics/locusValue"
|
|||
import "seekia/internal/genetics/prepareRawGenomes"
|
||||
import "seekia/internal/genetics/readRawGenomes"
|
||||
import "seekia/internal/genetics/geneticPrediction"
|
||||
import "seekia/internal/globalSettings"
|
||||
import "seekia/internal/helpers"
|
||||
import "seekia/internal/imagery"
|
||||
import "seekia/internal/localFilesystem"
|
||||
|
@ -46,12 +48,20 @@ import "time"
|
|||
|
||||
func main(){
|
||||
|
||||
polygenicDiseases.InitializePolygenicDiseaseVariables()
|
||||
|
||||
err := traits.InitializeTraitVariables()
|
||||
if (err != nil){
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
|
||||
err = globalSettings.InitializeGlobalSettingsDatastore()
|
||||
if (err != nil){
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
|
||||
app := app.New()
|
||||
|
||||
customTheme := getCustomFyneTheme()
|
||||
|
@ -209,7 +219,7 @@ func setHomePage(window fyne.Window){
|
|||
title := getBoldLabelCentered("Create Genetic Models Utility")
|
||||
|
||||
description1 := getLabelCentered("This utility is used to create the genetic prediction models.")
|
||||
description2 := getLabelCentered("These models are used to predict traits such as eye color from raw genome files.")
|
||||
description2 := getLabelCentered("These models are used to predict attributes such as eye color and autism from raw genome files.")
|
||||
description3 := getLabelCentered("Seekia aims to have open source and reproducible genetic prediction technology.")
|
||||
|
||||
step1Label := getLabelCentered("Step 1:")
|
||||
|
@ -722,16 +732,16 @@ func setStartAndMonitorCreateTrainingDataPage(window fyne.Window, previousPage f
|
|||
_, err = localFilesystem.CreateFolder("./TrainingData")
|
||||
if (err != nil) { return false, false, err }
|
||||
|
||||
//TODO: Add more traits
|
||||
traitNamesList := []string{"Eye Color", "Lactose Tolerance", "Height"}
|
||||
//TODO: Add more attributes
|
||||
attributeNamesList := []string{"Eye Color", "Lactose Tolerance", "Height", "Autism", "Homosexualness"}
|
||||
|
||||
// We create the folders for each trait's training data
|
||||
// We create the folders for each attribute's training data
|
||||
|
||||
for _, traitName := range traitNamesList{
|
||||
for _, attributeName := range attributeNamesList{
|
||||
|
||||
traitNameWithoutWhitespace := strings.ReplaceAll(traitName, " ", "")
|
||||
attributeNameWithoutWhitespace := strings.ReplaceAll(attributeName, " ", "")
|
||||
|
||||
folderpath := goFilepath.Join("./TrainingData/", traitNameWithoutWhitespace)
|
||||
folderpath := goFilepath.Join("./TrainingData/", attributeNameWithoutWhitespace)
|
||||
|
||||
_, err = localFilesystem.CreateFolder(folderpath)
|
||||
if (err != nil) { return false, false, err }
|
||||
|
@ -891,13 +901,13 @@ func setStartAndMonitorCreateTrainingDataPage(window fyne.Window, previousPage f
|
|||
continue
|
||||
}
|
||||
|
||||
for _, traitName := range traitNamesList{
|
||||
for _, attributeName := range attributeNamesList{
|
||||
|
||||
traitNameWithoutWhitespace := strings.ReplaceAll(traitName, " ", "")
|
||||
attributeNameWithoutWhitespace := strings.ReplaceAll(attributeName, " ", "")
|
||||
|
||||
trainingDataFolderpath := goFilepath.Join("./TrainingData", traitNameWithoutWhitespace)
|
||||
trainingDataFolderpath := goFilepath.Join("./TrainingData", attributeNameWithoutWhitespace)
|
||||
|
||||
userDataExists, userTrainingDataList, err := geneticPrediction.CreateGeneticPredictionTrainingData_OpenSNP(traitName, userPhenotypeDataObject, userLociValuesMap)
|
||||
userDataExists, userTrainingDataList, err := geneticPrediction.CreateGeneticPredictionTrainingData_OpenSNP(attributeName, userPhenotypeDataObject, userLociValuesMap)
|
||||
if (err != nil) { return false, false, err }
|
||||
if (userDataExists == false){
|
||||
// User cannot be used for training
|
||||
|
@ -991,35 +1001,35 @@ func setTrainModelsPage(window fyne.Window, previousPage func()){
|
|||
description1 := getLabelCentered("Press the button below to begin training a genetic model.")
|
||||
description2 := getLabelCentered("This will train a neural network using the user training data.")
|
||||
description3 := getLabelCentered("This will take a while.")
|
||||
description4 := getLabelCentered("You must select a trait model to train.")
|
||||
description4 := getLabelCentered("You must select a model to train.")
|
||||
|
||||
traitNamesList := []string{"Eye Color", "Lactose Tolerance", "Height"}
|
||||
attributeNamesList := []string{"Eye Color", "Lactose Tolerance", "Height", "Autism", "Homosexualness"}
|
||||
|
||||
traitNameSelector := widget.NewSelect(traitNamesList, nil)
|
||||
attributeNameSelector := widget.NewSelect(attributeNamesList, nil)
|
||||
|
||||
beginTrainingButton := getWidgetCentered(widget.NewButtonWithIcon("Begin Training Model", theme.MediaPlayIcon(), func(){
|
||||
|
||||
selectedTraitIndex := traitNameSelector.SelectedIndex()
|
||||
if (selectedTraitIndex < 0){
|
||||
title := "No Trait Selected"
|
||||
dialogMessage1 := getLabelCentered("You must select a trait model to train.")
|
||||
selectedAttributeIndex := attributeNameSelector.SelectedIndex()
|
||||
if (selectedAttributeIndex < 0){
|
||||
title := "No Attribute Selected"
|
||||
dialogMessage1 := getLabelCentered("You must select an attribute model to train.")
|
||||
dialogContent := container.NewVBox(dialogMessage1)
|
||||
dialog.ShowCustom(title, "Close", dialogContent, window)
|
||||
return
|
||||
}
|
||||
|
||||
traitName := traitNameSelector.Selected
|
||||
setStartAndMonitorTrainModelPage(window, traitName, currentPage)
|
||||
attributeName := attributeNameSelector.Selected
|
||||
setStartAndMonitorTrainModelPage(window, attributeName, currentPage)
|
||||
}))
|
||||
|
||||
traitNameSelectorCentered := getWidgetCentered(traitNameSelector)
|
||||
attributeNameSelectorCentered := getWidgetCentered(attributeNameSelector)
|
||||
|
||||
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, description4, widget.NewSeparator(), traitNameSelectorCentered, widget.NewSeparator(), beginTrainingButton)
|
||||
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, description4, widget.NewSeparator(), attributeNameSelectorCentered, widget.NewSeparator(), beginTrainingButton)
|
||||
|
||||
window.SetContent(page)
|
||||
}
|
||||
|
||||
func setStartAndMonitorTrainModelPage(window fyne.Window, traitName string, previousPage func()){
|
||||
func setStartAndMonitorTrainModelPage(window fyne.Window, attributeName string, previousPage func()){
|
||||
|
||||
title := getBoldLabelCentered("Train Model")
|
||||
|
||||
|
@ -1154,7 +1164,7 @@ func setStartAndMonitorTrainModelPage(window fyne.Window, traitName string, prev
|
|||
_, err := localFilesystem.CreateFolder("./TrainedModels")
|
||||
if (err != nil) { return false, err }
|
||||
|
||||
trainingSetFilepathsList, _, err := getTrainingAndTestingDataFilepathLists(traitName)
|
||||
trainingSetFilepathsList, _, err := getTrainingAndTestingDataFilepathLists(attributeName)
|
||||
if (err != nil) { return false, err }
|
||||
|
||||
// Now we deterministically randomize the order of the trainingSetFilepathsList
|
||||
|
@ -1165,7 +1175,7 @@ func setStartAndMonitorTrainModelPage(window fyne.Window, traitName string, prev
|
|||
})
|
||||
|
||||
// We create a new neural network object to train
|
||||
neuralNetworkObject, err := geneticPrediction.GetNewUntrainedNeuralNetworkObject(traitName)
|
||||
neuralNetworkObject, err := geneticPrediction.GetNewUntrainedNeuralNetworkObject(attributeName)
|
||||
if (err != nil) { return false, err }
|
||||
|
||||
// The number of rounds of training for the training data set
|
||||
|
@ -1253,21 +1263,28 @@ func setStartAndMonitorTrainModelPage(window fyne.Window, traitName string, prev
|
|||
return false, true, trainingDataObject, nil
|
||||
}
|
||||
|
||||
traitObject, err := traits.GetTraitObject(traitName)
|
||||
getAttributeIsNumericBool := func()(bool, error){
|
||||
|
||||
switch attributeName{
|
||||
|
||||
case "Height",
|
||||
"Autism",
|
||||
"Homosexualness":{
|
||||
return true, nil
|
||||
}
|
||||
case "Lactose Tolerance",
|
||||
"Eye Color":{
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, errors.New("setStartAndMonitorTrainModelPage called with unknown attributeName: " + attributeName)
|
||||
}
|
||||
|
||||
attributeIsNumeric, err := getAttributeIsNumericBool()
|
||||
if (err != nil) { return false, err }
|
||||
|
||||
getTraitIsNumericBool := func()bool{
|
||||
|
||||
traitIsDiscreteOrNumeric := traitObject.DiscreteOrNumeric
|
||||
if (traitIsDiscreteOrNumeric == "Numeric"){
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
traitIsNumeric := getTraitIsNumericBool()
|
||||
|
||||
processCompleted, err := geneticPrediction.TrainNeuralNetwork(traitName, traitIsNumeric, neuralNetworkObject, getNextTrainingDataFunction)
|
||||
processCompleted, err := geneticPrediction.TrainNeuralNetwork(attributeName, attributeIsNumeric, neuralNetworkObject, getNextTrainingDataFunction)
|
||||
if (err != nil) { return false, err }
|
||||
if (processCompleted == false){
|
||||
return false, nil
|
||||
|
@ -1279,9 +1296,9 @@ func setStartAndMonitorTrainModelPage(window fyne.Window, traitName string, prev
|
|||
neuralNetworkBytes, err := geneticPrediction.EncodeNeuralNetworkObjectToBytes(*neuralNetworkObject)
|
||||
if (err != nil) { return false, err }
|
||||
|
||||
traitNameWithoutWhitespaces := strings.ReplaceAll(traitName, " ", "")
|
||||
attributeNameWithoutWhitespaces := strings.ReplaceAll(attributeName, " ", "")
|
||||
|
||||
neuralNetworkFilename := traitNameWithoutWhitespaces + "Model.gob"
|
||||
neuralNetworkFilename := attributeNameWithoutWhitespaces + "Model.gob"
|
||||
|
||||
err = localFilesystem.CreateOrOverwriteFile(neuralNetworkBytes, "./TrainedModels/", neuralNetworkFilename)
|
||||
if (err != nil) { return false, err }
|
||||
|
@ -1343,36 +1360,36 @@ func setTestModelsPage(window fyne.Window, previousPage func()){
|
|||
description3 := getLabelCentered("The testing data is not used to train the models.")
|
||||
description4 := getLabelCentered("The results of the testing will be displayed at the end.")
|
||||
description5 := getLabelCentered("The results will also be saved in the ModelAccuracies folder.")
|
||||
description6 := getLabelCentered("You must select a trait model to test.")
|
||||
description6 := getLabelCentered("You must select a model to test.")
|
||||
|
||||
traitNamesList := []string{"Eye Color", "Lactose Tolerance", "Height"}
|
||||
attributeNamesList := []string{"Eye Color", "Lactose Tolerance", "Height", "Autism", "Homosexualness"}
|
||||
|
||||
traitNameSelector := widget.NewSelect(traitNamesList, nil)
|
||||
attributeNameSelector := widget.NewSelect(attributeNamesList, nil)
|
||||
|
||||
beginTestingButton := getWidgetCentered(widget.NewButtonWithIcon("Begin Testing Model", theme.MediaPlayIcon(), func(){
|
||||
|
||||
selectedTraitIndex := traitNameSelector.SelectedIndex()
|
||||
if (selectedTraitIndex < 0){
|
||||
title := "No Trait Selected"
|
||||
dialogMessage1 := getLabelCentered("You must select a trait model to test.")
|
||||
selectedAttributeIndex := attributeNameSelector.SelectedIndex()
|
||||
if (selectedAttributeIndex < 0){
|
||||
title := "No Attribute Selected"
|
||||
dialogMessage1 := getLabelCentered("You must select a model to test.")
|
||||
dialogContent := container.NewVBox(dialogMessage1)
|
||||
dialog.ShowCustom(title, "Close", dialogContent, window)
|
||||
return
|
||||
}
|
||||
|
||||
traitName := traitNameSelector.Selected
|
||||
attributeName := attributeNameSelector.Selected
|
||||
|
||||
setStartAndMonitorTestModelPage(window, traitName, currentPage)
|
||||
setStartAndMonitorTestModelPage(window, attributeName, currentPage)
|
||||
}))
|
||||
|
||||
traitNameSelectorCentered := getWidgetCentered(traitNameSelector)
|
||||
attributeNameSelectorCentered := getWidgetCentered(attributeNameSelector)
|
||||
|
||||
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, description4, description5, description6, widget.NewSeparator(), traitNameSelectorCentered, widget.NewSeparator(), beginTestingButton)
|
||||
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, description4, description5, description6, widget.NewSeparator(), attributeNameSelectorCentered, widget.NewSeparator(), beginTestingButton)
|
||||
|
||||
window.SetContent(page)
|
||||
}
|
||||
|
||||
func setStartAndMonitorTestModelPage(window fyne.Window, traitName string, previousPage func()){
|
||||
func setStartAndMonitorTestModelPage(window fyne.Window, attributeName string, previousPage func()){
|
||||
|
||||
title := getBoldLabelCentered("Testing Model")
|
||||
|
||||
|
@ -1409,17 +1426,35 @@ func setStartAndMonitorTestModelPage(window fyne.Window, traitName string, previ
|
|||
|
||||
window.SetContent(page)
|
||||
|
||||
testModelFunction := func(){
|
||||
getAttributeIsNumericBool := func()(bool, error){
|
||||
|
||||
traitObject, err := traits.GetTraitObject(traitName)
|
||||
switch attributeName{
|
||||
|
||||
case "Height",
|
||||
"Autism",
|
||||
"Homosexualness":{
|
||||
return true, nil
|
||||
}
|
||||
case "Lactose Tolerance",
|
||||
"Eye Color":{
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, errors.New("setStartAndMonitorTrainModelPage called with unknown attributeName: " + attributeName)
|
||||
}
|
||||
|
||||
attributeIsNumeric, err := getAttributeIsNumericBool()
|
||||
if (err != nil) {
|
||||
setErrorEncounteredPage(window, err, previousPage)
|
||||
setErrorEncounteredPage(window, errors.New("setStartAndMonitorTestModelPage called with unknown attributeName: " + attributeName), previousPage)
|
||||
return
|
||||
}
|
||||
|
||||
traitIsDiscreteOrNumeric := traitObject.DiscreteOrNumeric
|
||||
if (attributeIsNumeric == false){
|
||||
|
||||
if (traitIsDiscreteOrNumeric == "Discrete"){
|
||||
// attribute is a Discrete trait
|
||||
|
||||
testModelFunction := func(){
|
||||
|
||||
//Outputs:
|
||||
// -bool: Process completed (true == was not stopped mid-way)
|
||||
|
@ -1448,10 +1483,10 @@ func setStartAndMonitorTestModelPage(window fyne.Window, traitName string, previ
|
|||
traitPredictionInfoMap := make(map[geneticPrediction.DiscreteTraitOutcomeInfo]TraitAccuracyStatisticsValue)
|
||||
|
||||
|
||||
_, testingSetFilepathsList, err := getTrainingAndTestingDataFilepathLists(traitName)
|
||||
_, testingSetFilepathsList, err := getTrainingAndTestingDataFilepathLists(attributeName)
|
||||
if (err != nil) { return false, nil, err }
|
||||
|
||||
traitNameWithoutWhitespaces := strings.ReplaceAll(traitName, " ", "")
|
||||
traitNameWithoutWhitespaces := strings.ReplaceAll(attributeName, " ", "")
|
||||
|
||||
// We read the trained model for this trait
|
||||
modelFilename := traitNameWithoutWhitespaces + "Model.gob"
|
||||
|
@ -1504,10 +1539,10 @@ func setStartAndMonitorTestModelPage(window fyne.Window, traitName string, previ
|
|||
return false, nil, errors.New("Neural network prediction output length does not match expected output length.")
|
||||
}
|
||||
|
||||
correctOutcomeName, err := geneticPrediction.GetDiscreteOutcomeNameFromOutputLayer(traitName, true, trainingDataExpectedOutputLayer)
|
||||
correctOutcomeName, err := geneticPrediction.GetDiscreteOutcomeNameFromOutputLayer(attributeName, true, trainingDataExpectedOutputLayer)
|
||||
if (err != nil) { return false, nil, err }
|
||||
|
||||
predictedOutcomeName, err := geneticPrediction.GetDiscreteOutcomeNameFromOutputLayer(traitName, true, predictionLayer)
|
||||
predictedOutcomeName, err := geneticPrediction.GetDiscreteOutcomeNameFromOutputLayer(attributeName, true, predictionLayer)
|
||||
if (err != nil) { return false, nil, err }
|
||||
|
||||
getPredictionIsCorrectBool := func()bool{
|
||||
|
@ -1674,30 +1709,37 @@ func setStartAndMonitorTestModelPage(window fyne.Window, traitName string, previ
|
|||
return
|
||||
}
|
||||
|
||||
setViewModelTestingDiscreteTraitResultsPage(window, traitName, traitPredictionAccuracyInfoMap, previousPage)
|
||||
setViewModelTestingDiscreteTraitResultsPage(window, attributeName, traitPredictionAccuracyInfoMap, previousPage)
|
||||
}
|
||||
|
||||
go testModelFunction()
|
||||
|
||||
return
|
||||
|
||||
} else {
|
||||
|
||||
// traitIsDiscreteOrNumeric == "Numeric"
|
||||
// attribute is Numeric
|
||||
|
||||
testModelFunction := func(){
|
||||
|
||||
//Outputs:
|
||||
// -bool: Process completed (true == was not stopped mid-way)
|
||||
// -geneticPrediction.NumericTraitPredictionAccuracyInfoMap
|
||||
// -geneticPrediction.NumericAttributePredictionAccuracyInfoMap
|
||||
// -error
|
||||
testModel := func()(bool, geneticPrediction.NumericTraitPredictionAccuracyInfoMap, error){
|
||||
testModel := func()(bool, geneticPrediction.NumericAttributePredictionAccuracyInfoMap, error){
|
||||
|
||||
// We use this map to count up the information about predictions
|
||||
// We use information from this map to construct the final accuracy information map
|
||||
// Map Structure: NumericTraitPredictionInfo -> []float64 (List of distances for each prediction)
|
||||
traitPredictionInfoMap := make(map[geneticPrediction.NumericTraitPredictionInfo][]float64)
|
||||
// Map Structure: NumericAttributePredictionInfo -> []float64 (List of distances for each prediction)
|
||||
attributePredictionInfoMap := make(map[geneticPrediction.NumericAttributePredictionInfo][]float64)
|
||||
|
||||
_, testingSetFilepathsList, err := getTrainingAndTestingDataFilepathLists(traitName)
|
||||
_, testingSetFilepathsList, err := getTrainingAndTestingDataFilepathLists(attributeName)
|
||||
if (err != nil) { return false, nil, err }
|
||||
|
||||
traitNameWithoutWhitespaces := strings.ReplaceAll(traitName, " ", "")
|
||||
attributeNameWithoutWhitespaces := strings.ReplaceAll(attributeName, " ", "")
|
||||
|
||||
// We read the trained model for this trait
|
||||
modelFilename := traitNameWithoutWhitespaces + "Model.gob"
|
||||
// We read the trained model for this attribute
|
||||
modelFilename := attributeNameWithoutWhitespaces + "Model.gob"
|
||||
|
||||
trainedModelFilepath := goFilepath.Join("./TrainedModels/", modelFilename)
|
||||
|
||||
|
@ -1749,10 +1791,10 @@ func setStartAndMonitorTestModelPage(window fyne.Window, traitName string, previ
|
|||
return false, nil, errors.New("Neural network numeric prediction output layer length is not 1.")
|
||||
}
|
||||
|
||||
correctOutcomeValue, err := geneticPrediction.GetNumericOutcomeValueFromOutputLayer(traitName, trainingDataExpectedOutputLayer)
|
||||
correctOutcomeValue, err := geneticPrediction.GetNumericOutcomeValueFromOutputLayer(attributeName, trainingDataExpectedOutputLayer)
|
||||
if (err != nil) { return false, nil, err }
|
||||
|
||||
predictedOutcomeValue, err := geneticPrediction.GetNumericOutcomeValueFromOutputLayer(traitName, predictionLayer)
|
||||
predictedOutcomeValue, err := geneticPrediction.GetNumericOutcomeValueFromOutputLayer(attributeName, predictionLayer)
|
||||
if (err != nil) { return false, nil, err }
|
||||
|
||||
numberOfKnownLoci, numberOfKnownAndPhasedLoci, numberOfLoci, err := geneticPrediction.GetLociInfoFromNetworkInputLayer(trainingDataInputLayer)
|
||||
|
@ -1764,19 +1806,19 @@ func setStartAndMonitorTestModelPage(window fyne.Window, traitName string, previ
|
|||
proportionOfPhasedLoci := float64(numberOfKnownAndPhasedLoci)/float64(numberOfKnownLoci)
|
||||
percentageOfPhasedLoci := int(100*proportionOfPhasedLoci)
|
||||
|
||||
newNumericTraitPredictionInfo := geneticPrediction.NumericTraitPredictionInfo{
|
||||
newNumericAttributePredictionInfo := geneticPrediction.NumericAttributePredictionInfo{
|
||||
PercentageOfLociTested: percentageOfLociTested,
|
||||
PercentageOfPhasedLoci: percentageOfPhasedLoci,
|
||||
}
|
||||
|
||||
distanceFromCorrectValue := math.Abs(predictedOutcomeValue - correctOutcomeValue)
|
||||
|
||||
existingList, exists := traitPredictionInfoMap[newNumericTraitPredictionInfo]
|
||||
existingList, exists := attributePredictionInfoMap[newNumericAttributePredictionInfo]
|
||||
if (exists == false){
|
||||
traitPredictionInfoMap[newNumericTraitPredictionInfo] = []float64{distanceFromCorrectValue}
|
||||
attributePredictionInfoMap[newNumericAttributePredictionInfo] = []float64{distanceFromCorrectValue}
|
||||
} else {
|
||||
existingList = append(existingList, distanceFromCorrectValue)
|
||||
traitPredictionInfoMap[newNumericTraitPredictionInfo] = existingList
|
||||
attributePredictionInfoMap[newNumericAttributePredictionInfo] = existingList
|
||||
}
|
||||
|
||||
exampleIndexString := helpers.ConvertIntToString(index+1)
|
||||
|
@ -1789,20 +1831,20 @@ func setStartAndMonitorTestModelPage(window fyne.Window, traitName string, previ
|
|||
progressPercentageBinding.Set(newProgressFloat64)
|
||||
}
|
||||
|
||||
// Now we construct the TraitAccuracyInfoMap
|
||||
// Now we construct the AttributeAccuracyInfoMap
|
||||
|
||||
// This map stores the accuracy for each QuantityOfKnownLoci/QuantityOfPhasedLoci
|
||||
traitPredictionAccuracyInfoMap := make(map[geneticPrediction.NumericTraitPredictionInfo]geneticPrediction.NumericTraitPredictionAccuracyRangesMap)
|
||||
attributePredictionAccuracyInfoMap := make(map[geneticPrediction.NumericAttributePredictionInfo]geneticPrediction.NumericAttributePredictionAccuracyRangesMap)
|
||||
|
||||
for traitPredictionInfo, predictionDistancesList := range traitPredictionInfoMap{
|
||||
for attributePredictionInfo, predictionDistancesList := range attributePredictionInfoMap{
|
||||
|
||||
if (len(predictionDistancesList) == 0){
|
||||
return false, nil, errors.New("traitPredictionInfoMap contains empty predictionDistancesList.")
|
||||
return false, nil, errors.New("attributePredictionInfoMap contains empty predictionDistancesList.")
|
||||
}
|
||||
|
||||
// Map Structure: Accuracy Percentage (AP) -> Amount needed to deviate from prediction
|
||||
// for the value to be accurate (AP)% of the time
|
||||
newNumericTraitPredictionAccuracyRangesMap := make(map[int]float64)
|
||||
newNumericAttributePredictionAccuracyRangesMap := make(map[int]float64)
|
||||
|
||||
if (len(predictionDistancesList) < 5){
|
||||
// We don't have enough data to create an accuracyRanges map.
|
||||
|
@ -1825,7 +1867,7 @@ func setStartAndMonitorTestModelPage(window fyne.Window, traitName string, previ
|
|||
continue
|
||||
}
|
||||
|
||||
_, exists := newNumericTraitPredictionAccuracyRangesMap[percentageOfPredictionsWithinDistance]
|
||||
_, exists := newNumericAttributePredictionAccuracyRangesMap[percentageOfPredictionsWithinDistance]
|
||||
if (exists == true){
|
||||
// There exists a value for this percentage already
|
||||
// This happens because we convert a float64 to an int
|
||||
|
@ -1835,33 +1877,33 @@ func setStartAndMonitorTestModelPage(window fyne.Window, traitName string, previ
|
|||
continue
|
||||
}
|
||||
|
||||
newNumericTraitPredictionAccuracyRangesMap[percentageOfPredictionsWithinDistance] = distance
|
||||
newNumericAttributePredictionAccuracyRangesMap[percentageOfPredictionsWithinDistance] = distance
|
||||
}
|
||||
|
||||
traitPredictionAccuracyInfoMap[traitPredictionInfo] = newNumericTraitPredictionAccuracyRangesMap
|
||||
attributePredictionAccuracyInfoMap[attributePredictionInfo] = newNumericAttributePredictionAccuracyRangesMap
|
||||
}
|
||||
|
||||
// Testing is complete.
|
||||
|
||||
// We save the info map as a file in the ModelAccuracies folder
|
||||
|
||||
fileBytes, err := geneticPrediction.EncodeNumericTraitPredictionAccuracyInfoMapToBytes(traitPredictionAccuracyInfoMap)
|
||||
fileBytes, err := geneticPrediction.EncodeNumericAttributePredictionAccuracyInfoMapToBytes(attributePredictionAccuracyInfoMap)
|
||||
if (err != nil) { return false, nil, err }
|
||||
|
||||
_, err = localFilesystem.CreateFolder("./ModelAccuracies")
|
||||
if (err != nil) { return false, nil, err }
|
||||
|
||||
modelAccuracyFilename := traitNameWithoutWhitespaces + "ModelAccuracy.gob"
|
||||
modelAccuracyFilename := attributeNameWithoutWhitespaces + "ModelAccuracy.gob"
|
||||
|
||||
err = localFilesystem.CreateOrOverwriteFile(fileBytes, "./ModelAccuracies/", modelAccuracyFilename)
|
||||
if (err != nil) { return false, nil, err }
|
||||
|
||||
progressPercentageBinding.Set(1)
|
||||
|
||||
return true, traitPredictionAccuracyInfoMap, nil
|
||||
return true, attributePredictionAccuracyInfoMap, nil
|
||||
}
|
||||
|
||||
processIsComplete, traitPredictionAccuracyInfoMap, err := testModel()
|
||||
processIsComplete, attributePredictionAccuracyInfoMap, err := testModel()
|
||||
if (err != nil){
|
||||
setErrorEncounteredPage(window, err, previousPage)
|
||||
return
|
||||
|
@ -1871,12 +1913,13 @@ func setStartAndMonitorTestModelPage(window fyne.Window, traitName string, previ
|
|||
return
|
||||
}
|
||||
|
||||
setViewModelTestingNumericTraitResultsPage(window, traitName, traitPredictionAccuracyInfoMap, previousPage)
|
||||
}
|
||||
setViewModelTestingNumericAttributeResultsPage(window, attributeName, attributePredictionAccuracyInfoMap, previousPage)
|
||||
return
|
||||
}
|
||||
|
||||
go testModelFunction()
|
||||
}
|
||||
}
|
||||
|
||||
// This is a page to view the details of testing for a specific trait's model
|
||||
func setViewModelTestingDiscreteTraitResultsPage(window fyne.Window, traitName string, traitAccuracyInfoMap geneticPrediction.DiscreteTraitPredictionAccuracyInfoMap, exitPage func()){
|
||||
|
@ -2043,18 +2086,18 @@ func setViewModelTestingDiscreteTraitResultsPage(window fyne.Window, traitName s
|
|||
}
|
||||
|
||||
|
||||
// This is a page to view the details of testing for a specific trait's model
|
||||
func setViewModelTestingNumericTraitResultsPage(window fyne.Window, traitName string, traitAccuracyInfoMap geneticPrediction.NumericTraitPredictionAccuracyInfoMap, exitPage func()){
|
||||
// This is a page to view the details of testing for a numeric attribute's model
|
||||
func setViewModelTestingNumericAttributeResultsPage(window fyne.Window, attributeName string, attributeAccuracyInfoMap geneticPrediction.NumericAttributePredictionAccuracyInfoMap, exitPage func()){
|
||||
|
||||
title := getBoldLabelCentered("Numeric Trait Prediction Accuracy Details")
|
||||
title := getBoldLabelCentered("Numeric Attribute Prediction Accuracy Details")
|
||||
|
||||
exitButton := getWidgetCentered(widget.NewButtonWithIcon("Exit", theme.CancelIcon(), exitPage))
|
||||
|
||||
description1 := getLabelCentered("The results of the prediction accuracy for this trait are below.")
|
||||
description1 := getLabelCentered("The results of the prediction accuracy for this attribute are below.")
|
||||
|
||||
traitNameTitle := widget.NewLabel("Trait Name:")
|
||||
traitNameLabel := getBoldLabel(traitName)
|
||||
traitNameRow := container.NewHBox(layout.NewSpacer(), traitNameTitle, traitNameLabel, layout.NewSpacer())
|
||||
attributeNameTitle := widget.NewLabel("Attribute Name:")
|
||||
attributeNameLabel := getBoldLabel(attributeName)
|
||||
attributeNameRow := container.NewHBox(layout.NewSpacer(), attributeNameTitle, attributeNameLabel, layout.NewSpacer())
|
||||
|
||||
description2 := getLabelCentered("Each value is a range that the prediction must be widened by to be accurate X% of the time.")
|
||||
description3 := getLabelCentered("For example, for a height prediction to be accurate 90% of the time, allow a +/-10 cm range.")
|
||||
|
@ -2078,13 +2121,40 @@ func setViewModelTestingNumericTraitResultsPage(window fyne.Window, traitName st
|
|||
accuracyRangeColumn_34to66 := container.NewVBox(accuracyRangeTitle2, knownLociLabel_34to66, widget.NewSeparator())
|
||||
accuracyRangeColumn_67to100 := container.NewVBox(accuracyRangeTitle3, knownLociLabel_67to100, widget.NewSeparator())
|
||||
|
||||
traitObject, err := traits.GetTraitObject(traitName)
|
||||
// We get the formatter for the distance values
|
||||
// This converts raw predictions to formatted values
|
||||
// Example: 100 -> "100 centimeters"
|
||||
|
||||
getAttributeValueFormatter := func()(func(float64, bool)(string, error), error){
|
||||
switch attributeName{
|
||||
case "Homosexuality",
|
||||
"Height":{
|
||||
|
||||
traitObject, err := traits.GetTraitObject(attributeName)
|
||||
if (err != nil) { return nil, err }
|
||||
|
||||
traitIsDiscreteOrNumeric := traitObject.DiscreteOrNumeric
|
||||
if (traitIsDiscreteOrNumeric != "Numeric"){
|
||||
return nil, errors.New("setViewModelTestingNumericTraitResultsPage called with non-discrete trait: " + traitName)
|
||||
numericValueFormatter := traitObject.NumericValueFormatter
|
||||
|
||||
return numericValueFormatter, nil
|
||||
}
|
||||
}
|
||||
|
||||
// attribute is a polygenic disease
|
||||
|
||||
result := func(inputValue float64, _ bool)(string, error){
|
||||
|
||||
// Input value is a value between 0 and 10
|
||||
|
||||
inputValueFormatted := helpers.ConvertIntToString(int(inputValue))
|
||||
|
||||
return inputValueFormatted, nil
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
attributeValueFormatter, err := getAttributeValueFormatter()
|
||||
if (err != nil){ return nil, err }
|
||||
|
||||
probabilityMinimumRange := 1
|
||||
|
||||
|
@ -2125,11 +2195,11 @@ func setViewModelTestingNumericTraitResultsPage(window fyne.Window, traitName st
|
|||
predictionAccuracyDistancesSum_67to100 := float64(0)
|
||||
distancesCount_67to100 := 0
|
||||
|
||||
for traitOutcomeInfo, traitPredictionAccuracyRangesMap := range traitAccuracyInfoMap{
|
||||
for attributeOutcomeInfo, attributePredictionAccuracyRangesMap := range attributeAccuracyInfoMap{
|
||||
|
||||
percentageOfLociTested := traitOutcomeInfo.PercentageOfLociTested
|
||||
percentageOfLociTested := attributeOutcomeInfo.PercentageOfLociTested
|
||||
|
||||
for percentageCorrect, distance := range traitPredictionAccuracyRangesMap{
|
||||
for percentageCorrect, distance := range attributePredictionAccuracyRangesMap{
|
||||
|
||||
if (percentageCorrect < probabilityMinimumRange || percentageCorrect > probabilityMaximumRange){
|
||||
continue
|
||||
|
@ -2153,24 +2223,27 @@ func setViewModelTestingNumericTraitResultsPage(window fyne.Window, traitName st
|
|||
}
|
||||
}
|
||||
|
||||
getAverageAccuracyText := func(distancesSum float64, distancesCount int)string{
|
||||
getAverageAccuracyText := func(distancesSum float64, distancesCount int)(string, error){
|
||||
if (distancesCount == 0){
|
||||
return "Unknown"
|
||||
return "Unknown", nil
|
||||
}
|
||||
|
||||
averageDistance := distancesSum/float64(distancesCount)
|
||||
|
||||
averageDistanceString := helpers.ConvertFloat64ToStringRounded(averageDistance, 1)
|
||||
averageDistanceFormatted, err := attributeValueFormatter(averageDistance, false)
|
||||
if (err != nil) { return "", err }
|
||||
|
||||
//TODO: Retrieve units from traits package?
|
||||
result := "+/- " + averageDistanceString + " centimeters"
|
||||
result := "+/- " + averageDistanceFormatted
|
||||
|
||||
return result
|
||||
return result, nil
|
||||
}
|
||||
|
||||
averageDistanceText_0to33 := getAverageAccuracyText(predictionAccuracyDistancesSum_0to33, distancesCount_0to33)
|
||||
averageDistanceText_34to66 := getAverageAccuracyText(predictionAccuracyDistancesSum_34to66, distancesCount_34to66)
|
||||
averageDistanceText_67to100 := getAverageAccuracyText(predictionAccuracyDistancesSum_67to100, distancesCount_67to100)
|
||||
averageDistanceText_0to33, err := getAverageAccuracyText(predictionAccuracyDistancesSum_0to33, distancesCount_0to33)
|
||||
if (err != nil){ return nil, err }
|
||||
averageDistanceText_34to66, err := getAverageAccuracyText(predictionAccuracyDistancesSum_34to66, distancesCount_34to66)
|
||||
if (err != nil){ return nil, err }
|
||||
averageDistanceText_67to100, err := getAverageAccuracyText(predictionAccuracyDistancesSum_67to100, distancesCount_67to100)
|
||||
if (err != nil){ return nil, err }
|
||||
|
||||
averageDistanceLabel_0to33 := getBoldLabelCentered(averageDistanceText_0to33)
|
||||
averageDistanceLabel_34to66 := getBoldLabelCentered(averageDistanceText_34to66)
|
||||
|
@ -2204,7 +2277,7 @@ func setViewModelTestingNumericTraitResultsPage(window fyne.Window, traitName st
|
|||
return
|
||||
}
|
||||
|
||||
page := container.NewVBox(title, exitButton, widget.NewSeparator(), description1, widget.NewSeparator(), traitNameRow, widget.NewSeparator(), description2, description3, widget.NewSeparator(), resultsGrid)
|
||||
page := container.NewVBox(title, exitButton, widget.NewSeparator(), description1, widget.NewSeparator(), attributeNameRow, widget.NewSeparator(), description2, description3, widget.NewSeparator(), resultsGrid)
|
||||
|
||||
pageScrollable := container.NewVScroll(page)
|
||||
|
||||
|
@ -2212,20 +2285,16 @@ func setViewModelTestingNumericTraitResultsPage(window fyne.Window, traitName st
|
|||
}
|
||||
|
||||
|
||||
// This function returns a list of training data and testing data filepaths for a trait.
|
||||
// This function returns a list of training data and testing data filepaths for an attribute.
|
||||
//Outputs:
|
||||
// -[]string: Sorted list of training data filepaths
|
||||
// -[]string: Unsorted list of testing data filepaths
|
||||
// -error
|
||||
func getTrainingAndTestingDataFilepathLists(traitName string)([]string, []string, error){
|
||||
func getTrainingAndTestingDataFilepathLists(attributeName string)([]string, []string, error){
|
||||
|
||||
if (traitName != "Eye Color" && traitName != "Lactose Tolerance" && traitName != "Height"){
|
||||
return nil, nil, errors.New("getTrainingAndTestingDataFilepathLists called with invalid traitName: " + traitName)
|
||||
}
|
||||
attributeNameWithoutWhitespaces := strings.ReplaceAll(attributeName, " ", "")
|
||||
|
||||
traitNameWithoutWhitespaces := strings.ReplaceAll(traitName, " ", "")
|
||||
|
||||
trainingDataFolderpath := goFilepath.Join("./TrainingData/", traitNameWithoutWhitespaces)
|
||||
trainingDataFolderpath := goFilepath.Join("./TrainingData/", attributeNameWithoutWhitespaces)
|
||||
|
||||
filesList, err := os.ReadDir(trainingDataFolderpath)
|
||||
if (err != nil) { return nil, nil, err }
|
||||
|
@ -2238,7 +2307,7 @@ func getTrainingAndTestingDataFilepathLists(traitName string)([]string, []string
|
|||
filepathIsFolder := filesystemObject.IsDir()
|
||||
if (filepathIsFolder == true){
|
||||
// Folder is corrupt
|
||||
return nil, nil, errors.New("Training data is corrupt for trait: " + traitName)
|
||||
return nil, nil, errors.New("Training data is corrupt for attribute: " + attributeName)
|
||||
}
|
||||
|
||||
fileName := filesystemObject.Name()
|
||||
|
@ -2249,24 +2318,32 @@ func getTrainingAndTestingDataFilepathLists(traitName string)([]string, []string
|
|||
numberOfTrainingDataFiles := len(trainingDataFilenamesMap)
|
||||
|
||||
if (numberOfTrainingDataFiles == 0){
|
||||
return nil, nil, errors.New("No training data exists for trait: " + traitName)
|
||||
return nil, nil, errors.New("No training data exists for attribute: " + attributeName)
|
||||
}
|
||||
|
||||
getNumberOfExpectedTrainingDatas := func()(int, error){
|
||||
|
||||
if (traitName == "Eye Color"){
|
||||
switch attributeName{
|
||||
|
||||
return 113648, nil
|
||||
|
||||
} else if (traitName == "Lactose Tolerance"){
|
||||
case "Eye Color":{
|
||||
return 149894, nil
|
||||
|
||||
}
|
||||
case "Lactose Tolerance":{
|
||||
return 24872, nil
|
||||
} else if (traitName == "Height"){
|
||||
|
||||
}
|
||||
case "Height":{
|
||||
return 92281, nil
|
||||
}
|
||||
case "Autism":{
|
||||
return 32118, nil
|
||||
}
|
||||
case "Homosexualness":{
|
||||
return 14500, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, errors.New("Unknown traitName: " + traitName)
|
||||
return 0, errors.New("Unknown attributeName: " + attributeName)
|
||||
}
|
||||
|
||||
numberOfExpectedTrainingDatas, err := getNumberOfExpectedTrainingDatas()
|
||||
|
@ -2276,7 +2353,7 @@ func getTrainingAndTestingDataFilepathLists(traitName string)([]string, []string
|
|||
|
||||
numberOfTrainingDataFilesString := helpers.ConvertIntToString(numberOfTrainingDataFiles)
|
||||
|
||||
return nil, nil, errors.New(traitName + " quantity of training datas is unexpected: " + numberOfTrainingDataFilesString)
|
||||
return nil, nil, errors.New(attributeName + " quantity of training datas is unexpected: " + numberOfTrainingDataFilesString)
|
||||
}
|
||||
|
||||
// We sort the training data to be in a deterministically random order
|
||||
|
@ -2331,7 +2408,7 @@ func getTrainingAndTestingDataFilepathLists(traitName string)([]string, []string
|
|||
numberOfUsers := len(userIdentifiersList)
|
||||
|
||||
if (numberOfUsers < 250){
|
||||
return nil, nil, errors.New("Too few training data examples for trait: " + traitName)
|
||||
return nil, nil, errors.New("Too few training data examples for attribute: " + attributeName)
|
||||
}
|
||||
|
||||
// We use 200 users for testing (validation), so we don't train using them
|
||||
|
|
Loading…
Reference in a new issue