168 lines
5.4 KiB
Go
168 lines
5.4 KiB
Go
|
|
||
|
// polygenicDiseases provides information about polygenic diseases and the SNP base changes that effect a person's risk of becoming victim to them.
|
||
|
|
||
|
package polygenicDiseases
|
||
|
|
||
|
// Polygenic diseases are different from monogenicDiseases
|
||
|
// Monogenic diseases are well understood to be caused by mutations in a single gene, and thus have more accurate risk probabilities.
|
||
|
// 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 both polygenic disease and trait prediction.
|
||
|
// This package is currently a temporary, less accurate solution until we get access to the necessary training data.
|
||
|
// It may still be worth keeping this method in place for polygenic diseases and using neural networks in tandem.
|
||
|
|
||
|
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{
|
||
|
|
||
|
DiseaseName string
|
||
|
|
||
|
DiseaseDescription string
|
||
|
|
||
|
// Is either "Mate"/"Female"/"Both"
|
||
|
EffectedSex string
|
||
|
|
||
|
LociList []DiseaseLocus
|
||
|
|
||
|
// Inputs:
|
||
|
// -string: "Mate"/"Female"
|
||
|
// -int: Age
|
||
|
// Output:
|
||
|
// -float64: Average probability of having had the disease at that point in person's life
|
||
|
// -error
|
||
|
GetAverageRiskProbabilitiesFunction func(string, int)(float64, error)
|
||
|
|
||
|
// Map Structure: Reference name -> Reference link
|
||
|
References map[string]string
|
||
|
}
|
||
|
|
||
|
var polygenicDiseaseNamesList []string
|
||
|
var polygenicDiseaseObjectsList []PolygenicDisease
|
||
|
|
||
|
// This must be called once during application startup
|
||
|
func InitializePolygenicDiseaseVariables(){
|
||
|
|
||
|
breastCancerObject := getBreastCancerDiseaseObject()
|
||
|
|
||
|
polygenicDiseaseObjectsList = []PolygenicDisease{breastCancerObject}
|
||
|
|
||
|
polygenicDiseaseNamesList = make([]string, 0, len(polygenicDiseaseObjectsList))
|
||
|
|
||
|
for _, diseaseObject := range polygenicDiseaseObjectsList{
|
||
|
|
||
|
diseaseName := diseaseObject.DiseaseName
|
||
|
|
||
|
polygenicDiseaseNamesList = append(polygenicDiseaseNamesList, diseaseName)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Be aware that all of these functions are returning original objects/slices, not copies
|
||
|
// Thus, we cannot edit the objects/slices that are returned. We must copy the fields first if we want to edit them.
|
||
|
|
||
|
func GetPolygenicDiseaseNamesList()([]string, error){
|
||
|
|
||
|
if (polygenicDiseaseNamesList == nil){
|
||
|
return nil, errors.New("GetDiseaseNamesList called when list is not initialized.")
|
||
|
}
|
||
|
|
||
|
return polygenicDiseaseNamesList, nil
|
||
|
}
|
||
|
|
||
|
func GetPolygenicDiseaseObjectsList()([]PolygenicDisease, error){
|
||
|
|
||
|
if (polygenicDiseaseObjectsList == nil){
|
||
|
return nil, errors.New("GetPolygenicDiseaseObjectsList called when list is not initialized.")
|
||
|
}
|
||
|
|
||
|
return polygenicDiseaseObjectsList, nil
|
||
|
}
|
||
|
|
||
|
func GetPolygenicDiseaseObject(diseaseName string)(PolygenicDisease, error){
|
||
|
|
||
|
polygenicDiseaseObjectsList, err := GetPolygenicDiseaseObjectsList()
|
||
|
if (err != nil) { return PolygenicDisease{}, err }
|
||
|
|
||
|
for _, diseaseObject := range polygenicDiseaseObjectsList{
|
||
|
|
||
|
currentDiseaseName := diseaseObject.DiseaseName
|
||
|
if (currentDiseaseName != diseaseName){
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
return diseaseObject, nil
|
||
|
}
|
||
|
|
||
|
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
|
||
|
}
|
||
|
|
||
|
|
||
|
|