// trainedPredictionModels contains trained prediction neural network models for predicting genetic traits // These models are stored as .gob encoded files of []float32 weights // This package also contains prediction accuracy information for each model // Prediction accuracy models describe information about how accurate the predictions made by the models are // All of the files in this package are created by the Create Genetic Models utility. // This utility is located in /utilities/createGeneticModels/createGeneticModels.go package trainedPredictionModels import "seekia/internal/genetics/geneticPrediction" import "seekia/internal/genetics/geneticPredictionModels" import "seekia/internal/genetics/locusValue" import _ "embed" import "math" import "bytes" import "encoding/gob" import "slices" import "sync" import "errors" // These are the trained prediction model files: //go:embed predictionModels/EyeColorModel.gob var predictionModelFile_EyeColor []byte //go:embed predictionModels/LactoseToleranceModel.gob var predictionModelFile_LactoseTolerance []byte //go:embed predictionModels/HeightModel.gob var predictionModelFile_Height []byte //go:embed predictionModels/AutismModel.gob var predictionModelFile_Autism []byte //go:embed predictionModels/HomosexualnessModel.gob var predictionModelFile_Homosexualness []byte //go:embed predictionModels/ObesityModel.gob var predictionModelFile_Obesity []byte // These are the trained prediction models // Each model has a mutex so it will only be used to make 1 prediction at a time var predictionModel_EyeColor *geneticPredictionModels.NeuralNetwork var predictionModelMutex_EyeColor sync.Mutex var predictionModel_LactoseTolerance *geneticPredictionModels.NeuralNetwork var predictionModelMutex_LactoseTolerance sync.Mutex var predictionModel_Height *geneticPredictionModels.NeuralNetwork var predictionModelMutex_Height sync.Mutex var predictionModel_Autism *geneticPredictionModels.NeuralNetwork var predictionModelMutex_Autism sync.Mutex var predictionModel_Homosexualness *geneticPredictionModels.NeuralNetwork var predictionModelMutex_Homosexualness sync.Mutex var predictionModel_Obesity *geneticPredictionModels.NeuralNetwork var predictionModelMutex_Obesity sync.Mutex // These are the discrete trait prediction model accuracy files: //go:embed predictionModelAccuracies/EyeColorModelAccuracy.gob var predictionAccuracyFile_EyeColor []byte //go:embed predictionModelAccuracies/LactoseToleranceModelAccuracy.gob var predictionAccuracyFile_LactoseTolerance []byte // These are the discrete trait prediction model accuracy maps var predictionAccuracyMap_EyeColor DiscreteTraitPredictionAccuracyInfoMap var predictionAccuracyMap_LactoseTolerance DiscreteTraitPredictionAccuracyInfoMap // These are the numeric attribute prediction model accuracy files: //go:embed predictionModelAccuracies/HeightModelAccuracy.gob var predictionAccuracyFile_Height []byte //go:embed predictionModelAccuracies/AutismModelAccuracy.gob var predictionAccuracyFile_Autism []byte //go:embed predictionModelAccuracies/HomosexualnessModelAccuracy.gob var predictionAccuracyFile_Homosexualness []byte //go:embed predictionModelAccuracies/ObesityModelAccuracy.gob var predictionAccuracyFile_Obesity []byte // These are the numeric attribute prediction model accuracy maps var predictionAccuracyMap_Height NumericAttributePredictionAccuracyInfoMap var predictionAccuracyMap_Autism NumericAttributePredictionAccuracyInfoMap var predictionAccuracyMap_Homosexualness NumericAttributePredictionAccuracyInfoMap var predictionAccuracyMap_Obesity NumericAttributePredictionAccuracyInfoMap // This function has to be called once upon application startup // We must also call it before certain tests func InitializeTrainedPredictionModels()error{ // We first initialize the neural networks attributeNamesList := []string{"Eye Color", "Lactose Tolerance", "Height", "Autism", "Obesity", "Homosexualness"} for _, attributeName := range attributeNamesList{ getPredictionModelFileBytes := func()([]byte, error){ switch attributeName{ case "Eye Color":{ return predictionModelFile_EyeColor, nil } case "Lactose Tolerance":{ return predictionModelFile_LactoseTolerance, nil } case "Height":{ return predictionModelFile_Height, nil } case "Autism":{ return predictionModelFile_Autism, nil } case "Obesity":{ return predictionModelFile_Obesity, nil } case "Homosexualness":{ return predictionModelFile_Homosexualness, nil } } return nil, errors.New("Trying to initialize genetic prediction model with unknown attributeName: " + attributeName) } predictionModelFileBytes, err := getPredictionModelFileBytes() if (err != nil) { return err } neuralNetworkObject, err := geneticPredictionModels.DecodeBytesToNeuralNetworkObject(predictionModelFileBytes) if (err != nil) { return err } switch attributeName{ case "Eye Color":{ predictionModel_EyeColor = &neuralNetworkObject continue } case "Lactose Tolerance":{ predictionModel_LactoseTolerance = &neuralNetworkObject continue } case "Height":{ predictionModel_Height = &neuralNetworkObject continue } case "Autism":{ predictionModel_Autism = &neuralNetworkObject continue } case "Obesity":{ predictionModel_Obesity = &neuralNetworkObject continue } case "Homosexualness":{ predictionModel_Homosexualness = &neuralNetworkObject continue } } return errors.New("Trying to initialize genetic prediction model with unknown attributeName: " + attributeName) } // Now we initialize the prediction accuracy information // We start with discrete traits discreteTraitNamesList := []string{"Eye Color", "Lactose Tolerance"} for _, traitName := range discreteTraitNamesList{ getPredictionAccuracyFileBytes := func()([]byte, error){ switch traitName{ case "Eye Color":{ return predictionAccuracyFile_EyeColor, nil } case "Lactose Tolerance":{ return predictionAccuracyFile_LactoseTolerance, nil } } return nil, errors.New("Prediction accuracy file not found for discrete trait: " + traitName) } predictionAccuracyFileBytes, err := getPredictionAccuracyFileBytes() if (err != nil) { return err } // We convert the gob encoded file to a map discreteTraitPredictionAccuracyInfoMap, err := decodeBytesToDiscreteTraitPredictionAccuracyInfoMap(predictionAccuracyFileBytes) if (err != nil) { return err } // We initialize the global variables switch traitName{ case "Eye Color":{ predictionAccuracyMap_EyeColor = discreteTraitPredictionAccuracyInfoMap continue } case "Lactose Tolerance":{ predictionAccuracyMap_LactoseTolerance = discreteTraitPredictionAccuracyInfoMap continue } } return errors.New("Unknown discrete trait name: " + traitName) } // Now we process numeric attributes numericAttributeNamesList := []string{"Height", "Autism", "Homosexualness", "Obesity"} for _, traitName := range numericAttributeNamesList{ getPredictionAccuracyFileBytes := func()([]byte, error){ switch traitName{ case "Height":{ return predictionAccuracyFile_Height, nil } case "Autism":{ return predictionAccuracyFile_Autism, nil } case "Homosexualness":{ return predictionAccuracyFile_Homosexualness, nil } case "Obesity":{ return predictionAccuracyFile_Obesity, nil } } return nil, errors.New("Prediction accuracy file not found for numeric trait: " + traitName) } predictionAccuracyFileBytes, err := getPredictionAccuracyFileBytes() if (err != nil) { return err } // We convert the gob encoded file to a map numericTraitPredictionAccuracyInfoMap, err := decodeBytesToNumericAttributePredictionAccuracyInfoMap(predictionAccuracyFileBytes) if (err != nil) { return err } // We initialize the global variables switch traitName{ case "Height":{ predictionAccuracyMap_Height = numericTraitPredictionAccuracyInfoMap continue } case "Autism":{ predictionAccuracyMap_Autism = numericTraitPredictionAccuracyInfoMap continue } case "Homosexualness":{ predictionAccuracyMap_Homosexualness = numericTraitPredictionAccuracyInfoMap continue } case "Obesity":{ predictionAccuracyMap_Obesity = numericTraitPredictionAccuracyInfoMap continue } } return errors.New("Unknown numeric trait name: " + traitName) } return nil } // We use this to check if a neural network exists for an attribute func CheckIfAttributeNeuralNetworkExists(attributeName string)bool{ switch attributeName{ case "Eye Color", "Lactose Tolerance", "Height", "Autism", "Obesity", "Homosexualness":{ return true } } return false } //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) // -string: Predicted trait outcome (Example: "Blue") // -int: Confidence: Probability (0-100) that the prediction is accurate // -int: Quantity of loci known // -int: Quantity of phased loci // -error func GetNeuralNetworkDiscreteTraitPredictionFromGenomeMap(traitName string, traitRSIDsList []int64, genomeMap map[int64]locusValue.LocusValue)(bool, bool, string, int, int, int, error){ getPredictionModelObject := func()(bool, *geneticPredictionModels.NeuralNetwork){ switch traitName{ case "Eye Color":{ return true, predictionModel_EyeColor } case "Lactose Tolerance":{ return true, predictionModel_LactoseTolerance } } return false, nil } predictionModelExists, predictionModelObject := getPredictionModelObject() if (predictionModelExists == false){ // Neural network trait prediction is not possible for this trait return false, false, "", 0, 0, 0, nil } if (predictionModelObject == nil){ return false, false, "", 0, 0, 0, errors.New("GetNeuralNetworkDiscreteTraitPredictionFromGenomeMap called when trained prediction models are not initialized.") } if (len(traitRSIDsList) == 0){ return false, false, "", 0, 0, 0, errors.New("GetNeuralNetworkDiscreteTraitPredictionFromGenomeMap called with empty traitRSIDsList for trait with a neural network.") } traitRSIDsListCopy := slices.Clone(traitRSIDsList) slices.Sort(traitRSIDsListCopy) neuralNetworkInput, quantityOfLociKnown, quantityOfPhasedLoci, err := geneticPrediction.CreateInputNeuralNetworkLayerFromGenomeMap(traitRSIDsListCopy, genomeMap) if (err != nil) { return false, false, "", 0, 0, 0, err } if (quantityOfLociKnown == 0){ // We can't predict anything about this trait for this genome return true, false, "", 0, 0, 0, nil } getPredictionOutcome := func()(string, error){ // We lock the mutex for the prediction model switch traitName{ case "Eye Color":{ predictionModelMutex_EyeColor.Lock() defer predictionModelMutex_EyeColor.Unlock() } case "Lactose Tolerance":{ predictionModelMutex_LactoseTolerance.Lock() defer predictionModelMutex_LactoseTolerance.Unlock() } default:{ return "", errors.New("traitName not found: " + traitName) } } outputLayer, err := geneticPrediction.GetNeuralNetworkRawPrediction(predictionModelObject, false, neuralNetworkInput) if (err != nil) { return "", err } predictedOutcomeName, err := geneticPrediction.GetDiscreteOutcomeNameFromOutputLayer(traitName, false, outputLayer) if (err != nil) { return "", err } return predictedOutcomeName, nil } predictedOutcome, err := getPredictionOutcome() if (err != nil) { return false, false, "", 0, 0, 0, err } modelTraitAccuracyInfoMap, err := GetPredictionModelDiscreteTraitAccuracyInfoMap(traitName) if (err != nil) { return false, false, "", 0, 0, 0, err } // We find the model trait accuracy info object that is the most similar to our predicted outcome getPredictionAccuracy := func()int{ totalNumberOfTraitLoci := len(traitRSIDsList) proportionOfLociTested := float64(quantityOfLociKnown)/float64(totalNumberOfTraitLoci) percentageOfLociTested := int(proportionOfLociTested * 100) proportionOfPhasedLoci := float64(quantityOfPhasedLoci)/float64(totalNumberOfTraitLoci) percentageOfPhasedLoci := int(proportionOfPhasedLoci * 100) // This is a value between 0 and 100 that represents the most likely accuracy probability for this prediction closestPredictionAccuracy := 0 // This is a value that represents the distance our closest prediction accuracy has from the current prediction // Consider each prediction accuracy value on an (X,Y) coordinate plane // X = Number of loci tested // Y = Number of phased loci closestPredictionAccuracyDistance := float64(0) anyOutcomeAccuracyFound := false for traitOutcomeInfo, traitPredictionAccuracyInfo := range modelTraitAccuracyInfoMap{ outcomeName := traitOutcomeInfo.OutcomeName if (outcomeName != predictedOutcome){ continue } probabilityOfCorrectOutcomePrediction := traitPredictionAccuracyInfo.ProbabilityOfCorrectOutcomePrediction currentPercentageOfLociTested := traitOutcomeInfo.PercentageOfLociTested currentPercentageOfPhasedLoci := traitOutcomeInfo.PercentageOfPhasedLoci // Distance Formula for 2 coordinates (x1, y1) and (x2, y2): // distance = √((x2 - x1)^2 + (y2 - y1)^2) differenceInX := float64(currentPercentageOfLociTested - percentageOfLociTested) differenceInY := float64(currentPercentageOfPhasedLoci - percentageOfPhasedLoci) distance := math.Sqrt(math.Pow(differenceInX, 2) + math.Pow(differenceInY, 2)) if (distance == 0){ // We found the exact prediction accuracy return probabilityOfCorrectOutcomePrediction } if (anyOutcomeAccuracyFound == false){ closestPredictionAccuracyDistance = distance closestPredictionAccuracy = probabilityOfCorrectOutcomePrediction anyOutcomeAccuracyFound = true continue } else { if (distance < closestPredictionAccuracyDistance){ closestPredictionAccuracyDistance = distance closestPredictionAccuracy = probabilityOfCorrectOutcomePrediction } } } if (anyOutcomeAccuracyFound == false){ // This means that our model has never actually predicted this outcome // This shouldn't happen unless our model is really bad, or our training set has very few people with this outcome. // We return a 0% accuracy rating return 0 } return closestPredictionAccuracy } predictionAccuracy := getPredictionAccuracy() return true, true, predictedOutcome, 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 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 GetNeuralNetworkNumericAttributePredictionFromGenomeMap(attributeName string, attributeLociList []int64, genomeMap map[int64]locusValue.LocusValue)(bool, bool, float64, map[int]float64, int, int, error){ getPredictionModelObject := func()(bool, *geneticPredictionModels.NeuralNetwork){ switch attributeName{ case "Height":{ return true, predictionModel_Height } case "Autism":{ return true, predictionModel_Autism } case "Obesity":{ return true, predictionModel_Obesity } case "Homosexualness":{ return true, predictionModel_Homosexualness } } return false, nil } predictionModelExists, predictionModelObject := getPredictionModelObject() if (predictionModelExists == false){ // Neural network trait prediction is not possible for this trait return false, false, 0, nil, 0, 0, nil } if (predictionModelObject == nil){ return false, false, 0, nil, 0, 0, errors.New("GetNeuralNetworkNumericAttributePredictionFromGenomeMap called when trained prediction models are not initialized.") } if (len(attributeLociList) == 0){ return false, false, 0, nil, 0, 0, errors.New("GetNeuralNetworkNumericAttributePredictionFromGenomeMap called with empty attributeLociList for an attribute with a neural network.") } attributeLociListCopy := slices.Clone(attributeLociList) slices.Sort(attributeLociListCopy) neuralNetworkInput, quantityOfLociKnown, quantityOfPhasedLoci, err := geneticPrediction.CreateInputNeuralNetworkLayerFromGenomeMap(attributeLociListCopy, genomeMap) if (err != nil) { return false, false, 0, nil, 0, 0, err } if (quantityOfLociKnown == 0){ // We can't predict anything about this attribute for this genome return true, false, 0, nil, 0, 0, nil } getPredictionOutcome := func()(float64, error){ // We lock the mutex for the prediction model switch attributeName{ case "Height":{ predictionModelMutex_Height.Lock() defer predictionModelMutex_Height.Unlock() } case "Autism":{ predictionModelMutex_Autism.Lock() defer predictionModelMutex_Autism.Unlock() } case "Obesity":{ predictionModelMutex_Obesity.Lock() defer predictionModelMutex_Obesity.Unlock() } case "Homosexualness":{ predictionModelMutex_Homosexualness.Lock() defer predictionModelMutex_Homosexualness.Unlock() } default:{ return 0, errors.New("attributeName not found: " + attributeName) } } outputLayer, err := geneticPrediction.GetNeuralNetworkRawPrediction(predictionModelObject, true, neuralNetworkInput) if (err != nil) { return 0, err } predictedOutcomeValue, err := geneticPrediction.GetNumericOutcomeValueFromOutputLayer(attributeName, outputLayer) if (err != nil) { return 0, err } return predictedOutcomeValue, nil } predictedOutcome, err := getPredictionOutcome() if (err != nil) { return false, false, 0, nil, 0, 0, err } modelAccuracyInfoMap, err := GetPredictionModelNumericAttributeAccuracyInfoMap(attributeName) 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{ totalNumberOfAttributeLoci := len(attributeLociListCopy) proportionOfLociTested := float64(quantityOfLociKnown)/float64(totalNumberOfAttributeLoci) percentageOfLociTested := int(proportionOfLociTested * 100) 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 var closestPredictionConfidenceRangesMap map[int]float64 // This is a value that represents the distance our closest prediction confidence ranges map has from the current prediction // Consider each prediction accuracy value on an (X,Y) coordinate plane // X = Number of loci tested // Y = Number of phased loci closestPredictionConfidenceRangesMapDistance := float64(0) for attributeOutcomeInfo, attributePredictionConfidenceRangesMap := range modelAccuracyInfoMap{ currentPercentageOfLociTested := attributeOutcomeInfo.PercentageOfLociTested currentPercentageOfPhasedLoci := attributeOutcomeInfo.PercentageOfPhasedLoci // Distance Formula for 2 coordinates (x1, y1) and (x2, y2): // distance = √((x2 - x1)^2 + (y2 - y1)^2) differenceInX := float64(currentPercentageOfLociTested - percentageOfLociTested) differenceInY := float64(currentPercentageOfPhasedLoci - percentageOfPhasedLoci) distance := math.Sqrt(math.Pow(differenceInX, 2) + math.Pow(differenceInY, 2)) if (distance == 0){ // We found the exact prediction confidence ranges map return attributePredictionConfidenceRangesMap } if (closestPredictionConfidenceRangesMap == nil || distance < closestPredictionConfidenceRangesMapDistance){ closestPredictionConfidenceRangesMapDistance = distance closestPredictionConfidenceRangesMap = attributePredictionConfidenceRangesMap } } return closestPredictionConfidenceRangesMap } predictionConfidenceRangesMap := getPredictionConfidenceRangesMap() return true, true, predictedOutcome, predictionConfidenceRangesMap, quantityOfLociKnown, quantityOfPhasedLoci, nil } // This map is used to store information about how accurate genetic prediction models are for discrete traits // Map Structure: Discrete Trait Outcome Info -> Discrete Trait Prediction Accuracy Info type DiscreteTraitPredictionAccuracyInfoMap map[DiscreteTraitOutcomeInfo]DiscreteTraitPredictionAccuracyInfo type DiscreteTraitOutcomeInfo struct{ // This is the outcome which was predicted // Example: "Blue" OutcomeName string // 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 // This is a value between 0-100 which describes the percentage of the tested loci which were phased for the input for the prediction PercentageOfPhasedLoci int } type DiscreteTraitPredictionAccuracyInfo struct{ // This contains the quantity of examples for the outcome with the specified percentageOfLociTested and percentageOfPhasedLoci QuantityOfExamples int // This contains the quantity of predictions for the outcome with the specified percentageOfLociTested and percentageOfPhasedLoci // Prediction = our model predicted this outcome QuantityOfPredictions int // This stores the probability (0-100) that our model will accurately predict this outcome for a genome which has // the specified percentageOfLociTested and percentageOfPhasedLoci // In other words: What is the probability that if you give Seekia a blue-eyed genome, it will give you a correct Blue prediction? // This value is only accurate is QuantityOfExamples > 0 ProbabilityOfCorrectGenomePrediction int // This stores the probability (0-100) that our model is correct if our model predicts that a genome // with the specified percentageOfLociTested and percentageOfPhasedLoci has this outcome // In other words: What is the probability that if Seekia says a genome will have blue eyes, it is correct? // This value is only accurate is QuantityOfPredictions > 0 ProbabilityOfCorrectOutcomePrediction int } func EncodeDiscreteTraitPredictionAccuracyInfoMapToBytes(inputMap DiscreteTraitPredictionAccuracyInfoMap)([]byte, error){ buffer := new(bytes.Buffer) encoder := gob.NewEncoder(buffer) err := encoder.Encode(inputMap) if (err != nil) { return nil, err } inputMapBytes := buffer.Bytes() return inputMapBytes, nil } func decodeBytesToDiscreteTraitPredictionAccuracyInfoMap(inputBytes []byte)(DiscreteTraitPredictionAccuracyInfoMap, error){ if (inputBytes == nil){ return nil, errors.New("DecodeBytesToDiscreteTraitPredictionAccuracyInfoMap called with nil inputBytes.") } buffer := bytes.NewBuffer(inputBytes) decoder := gob.NewDecoder(buffer) var newDiscreteTraitPredictionAccuracyInfoMap DiscreteTraitPredictionAccuracyInfoMap err := decoder.Decode(&newDiscreteTraitPredictionAccuracyInfoMap) if (err != nil){ return nil, err } return newDiscreteTraitPredictionAccuracyInfoMap, nil } type NumericAttributePredictionAccuracyInfoMap map[NumericAttributePredictionInfo]NumericAttributePredictionAccuracyRangesMap 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 // This is a value between 0-100 which describes the percentage of the tested loci which were phased for the input for the prediction PercentageOfPhasedLoci int } // Map Structure: Accuracy Percentage (AP) -> Amount needed to deviate from prediction for the value to be accurate (AP)% of the time // For example, if the model predicted that someone was 150 centimeters tall, how many centimeters would we have to deviate in both directions // in order for the true outcome to fall into the range 10% of the time, 20% of the time, 30% of the time, etc... // Example: // -90%+: 50 centimeters // If you travel 50 centimeters in both directions from the prediction, // the true height value will fall into this range 90% of the time. // -50%+: 20 centimeters // -10%+: 10 centimeters type NumericAttributePredictionAccuracyRangesMap map[int]float64 func EncodeNumericAttributePredictionAccuracyInfoMapToBytes(inputMap NumericAttributePredictionAccuracyInfoMap)([]byte, error){ buffer := new(bytes.Buffer) encoder := gob.NewEncoder(buffer) err := encoder.Encode(inputMap) if (err != nil) { return nil, err } inputMapBytes := buffer.Bytes() return inputMapBytes, nil } func decodeBytesToNumericAttributePredictionAccuracyInfoMap(inputBytes []byte)(NumericAttributePredictionAccuracyInfoMap, error){ if (inputBytes == nil){ return nil, errors.New("DecodeBytesToNumericAttributePredictionAccuracyInfoMap called with nil inputBytes.") } buffer := bytes.NewBuffer(inputBytes) decoder := gob.NewDecoder(buffer) var newNumericAttributePredictionAccuracyInfoMap NumericAttributePredictionAccuracyInfoMap err := decoder.Decode(&newNumericAttributePredictionAccuracyInfoMap) if (err != nil){ return nil, err } return newNumericAttributePredictionAccuracyInfoMap, nil } func GetPredictionModelDiscreteTraitAccuracyInfoMap(traitName string)(DiscreteTraitPredictionAccuracyInfoMap, error){ getAccuracyInfoMap := func()(DiscreteTraitPredictionAccuracyInfoMap, error){ switch traitName{ case "Eye Color":{ return predictionAccuracyMap_EyeColor, nil } case "Lactose Tolerance":{ return predictionAccuracyMap_LactoseTolerance, nil } } return nil, errors.New("GetPredictionModelDiscreteTraitAccuracyInfoMap called with unknown traitName: " + traitName) } accuracyInfoMap, err := getAccuracyInfoMap() if (err != nil) { return nil, err } if (accuracyInfoMap == nil){ return nil, errors.New("GetPredictionModelDiscreteTraitAccuracyInfoMap called when map is not initialized.") } return accuracyInfoMap, nil } // The files returned by this function are .gob encoded geneticPrediction.NumericAttributePredictionAccuracyInfoMap objects func GetPredictionModelNumericAttributeAccuracyInfoMap(attributeName string)(NumericAttributePredictionAccuracyInfoMap, error){ getAccuracyInfoMap := func()(NumericAttributePredictionAccuracyInfoMap, error){ switch attributeName{ case "Height":{ return predictionAccuracyMap_Height, nil } case "Autism":{ return predictionAccuracyMap_Autism, nil } case "Homosexualness":{ return predictionAccuracyMap_Homosexualness, nil } case "Obesity":{ return predictionAccuracyMap_Obesity, nil } } return nil, errors.New("GetPredictionModelNumericAttributeAccuracyInfoMap called with unknown attributeName: " + attributeName) } accuracyInfoMap, err := getAccuracyInfoMap() if (err != nil) { return nil, err } if (accuracyInfoMap == nil){ return nil, errors.New("GetPredictionModelNumericAttributeAccuracyInfoMap called when map is not initialized.") } return accuracyInfoMap, nil }