187 lines
7.9 KiB
Go
187 lines
7.9 KiB
Go
|
|
// myChosenAnalysis provides a function to get a mate user's chosen genetic analysis
|
|
// Mate users choose a genome person and genome in the Build Profile gui.
|
|
// The genome person's analysis is used for calculating genetic attributes with other users and for sharing on their profile
|
|
// The user can choose to not share any of the genetic analysis information on their profile, in which case
|
|
// the analysis is only used when calculating attributes with other users
|
|
// An example of one of these calculated attributes is "OffspringProbabilityOfAnyMonogenicDisease"
|
|
|
|
package myChosenAnalysis
|
|
|
|
import "seekia/internal/genetics/geneticAnalysis"
|
|
import "seekia/internal/genetics/myAnalyses"
|
|
import "seekia/internal/genetics/myPeople"
|
|
import "seekia/internal/genetics/readGeneticAnalysis"
|
|
import "seekia/internal/profiles/myLocalProfiles"
|
|
|
|
import "errors"
|
|
import "sync"
|
|
|
|
|
|
// We use this mutex whenever we update the cacheChosenGeneticAnalysis global variables
|
|
var myCacheChosenGeneticAnalysisMutex sync.RWMutex
|
|
|
|
// We use this identifier to keep track of which analysis we have stored in the cache
|
|
// Whenever we update our genome person's analysis, we will update our cache analysis
|
|
var myCacheChosenGeneticAnalysisIdentifier string
|
|
|
|
// We use this variable to store the analysis in memory
|
|
// This prevents us from having to read and unmarshal the messagepack file each time we want to retrieve the analysis
|
|
var myCacheChosenGeneticAnalysis geneticAnalysis.PersonAnalysis
|
|
|
|
// These variables store metadata about the cache genetic analysis
|
|
var myCacheChosenGeneticAnalysis_GenomeIdentifierToUse [16]byte
|
|
|
|
// This variable tells us if the current cache chosen genetic analysis contains multiple genomes
|
|
var myCacheChosenGeneticAnalysis_MultipleGenomesExist bool
|
|
|
|
|
|
// This function is used to retrieve the user's chosen person genetic analysis
|
|
// The user must choose a person to link to their mate profile/identity
|
|
// This genetic analysis is not shared on the person's profile publicly.
|
|
// Portions of the analysis may be shared if the user opts in.
|
|
// The analysis returned by this function is not a copy, so fields must not be edited
|
|
//Outputs:
|
|
// -bool: Person identifier chosen
|
|
// -bool: Any genomes exist
|
|
// -bool: Person analysis is ready
|
|
// -geneticAnalysis.PersonAnalysis: My Chosen Genetic analysis
|
|
// -[16]byte: Genome identifier to use
|
|
// -bool: Multiple genomes exist
|
|
// -error
|
|
func GetMyChosenMateGeneticAnalysis()(bool, bool, bool, geneticAnalysis.PersonAnalysis, [16]byte, bool, error){
|
|
|
|
// We use this when returning errors
|
|
emptyPersonAnalysis := geneticAnalysis.PersonAnalysis{}
|
|
|
|
// We check if the user has added a genome person, and add their genome info if necessary
|
|
|
|
myGenomePersonIdentifierExists, myGenomePersonIdentifier, err := myLocalProfiles.GetProfileData("Mate", "GenomePersonIdentifier")
|
|
if (err != nil){ return false, false, false, emptyPersonAnalysis, [16]byte{}, false, err }
|
|
if (myGenomePersonIdentifierExists == false){
|
|
return false, false, false, emptyPersonAnalysis, [16]byte{}, false, nil
|
|
}
|
|
|
|
anyGenomesExist, personAnalysisIsReady, personAnalysisIdentifier, err := myPeople.CheckIfPersonAnalysisIsReady(myGenomePersonIdentifier)
|
|
if (err != nil){ return false, false, false, emptyPersonAnalysis, [16]byte{}, false, err }
|
|
if (anyGenomesExist == false){
|
|
return true, false, false, emptyPersonAnalysis, [16]byte{}, false, nil
|
|
}
|
|
if (personAnalysisIsReady == false){
|
|
return true, true, false, emptyPersonAnalysis, [16]byte{}, false, nil
|
|
}
|
|
|
|
myCacheChosenGeneticAnalysisMutex.RLock()
|
|
myCacheChosenGeneticAnalysisIdentifierCopy := myCacheChosenGeneticAnalysisIdentifier
|
|
myCacheChosenGeneticAnalysisMutex.RUnlock()
|
|
|
|
if (myCacheChosenGeneticAnalysisIdentifierCopy == personAnalysisIdentifier){
|
|
// The analysis exists in cache
|
|
// We copy it and return it
|
|
|
|
myCacheChosenGeneticAnalysisMutex.RLock()
|
|
|
|
// This is a shallow copy, but it is all we need, because we never directly edit attributes of the returned object
|
|
myCacheChosenGeneticAnalysisCopy := myCacheChosenGeneticAnalysis
|
|
|
|
myCacheChosenGeneticAnalysis_GenomeIdentifierToUseCopy := myCacheChosenGeneticAnalysis_GenomeIdentifierToUse
|
|
myCacheChosenGeneticAnalysis_MultipleGenomesExistCopy := myCacheChosenGeneticAnalysis_MultipleGenomesExist
|
|
|
|
myCacheChosenGeneticAnalysisMutex.RUnlock()
|
|
|
|
return true, true, true, myCacheChosenGeneticAnalysisCopy, myCacheChosenGeneticAnalysis_GenomeIdentifierToUseCopy, myCacheChosenGeneticAnalysis_MultipleGenomesExistCopy, nil
|
|
}
|
|
|
|
// The analysis and its metadata have not been read into the cache yet
|
|
// We will retrieve it from its .messagepack file
|
|
|
|
myAnalysisFound, myGeneticAnalysisObject, err := myAnalyses.GetPersonGeneticAnalysis(personAnalysisIdentifier)
|
|
if (err != nil){ return false, false, false, emptyPersonAnalysis, [16]byte{}, false, err }
|
|
if (myAnalysisFound == false){
|
|
return false, false, false, emptyPersonAnalysis, [16]byte{}, false, errors.New("CheckIfPersonAnalysisIsReady returning missing genetic analysis.")
|
|
}
|
|
|
|
allRawGenomeIdentifiersList, multipleGenomesExist, onlyExcludeConflictsGenomeIdentifier, onlyIncludeSharedGenomeIdentifier, _, err := readGeneticAnalysis.GetMetadataFromPersonGeneticAnalysis(myGeneticAnalysisObject)
|
|
if (err != nil) { return false, false, false, emptyPersonAnalysis, [16]byte{}, false, err }
|
|
|
|
getGenomeIdentifierToUse := func()([16]byte, error){
|
|
|
|
if (multipleGenomesExist == false){
|
|
|
|
// The analysis only has 1 genome identifier.
|
|
analysisOnlyRawGenomeIdentifier := allRawGenomeIdentifiersList[0]
|
|
|
|
return analysisOnlyRawGenomeIdentifier, nil
|
|
}
|
|
|
|
currentCombinedGenomeToUse, err := GetMyCombinedGenomeToUse()
|
|
if (err != nil){ return [16]byte{}, err }
|
|
|
|
if (currentCombinedGenomeToUse == "Only Exclude Conflicts"){
|
|
return onlyExcludeConflictsGenomeIdentifier, nil
|
|
}
|
|
// currentCombinedGenomeToUse == "Only Include Shared"
|
|
return onlyIncludeSharedGenomeIdentifier, nil
|
|
}
|
|
|
|
genomeIdentifierToUse, err := getGenomeIdentifierToUse()
|
|
if (err != nil) { return false, false, false, emptyPersonAnalysis, [16]byte{}, false, err }
|
|
|
|
myCacheChosenGeneticAnalysisMutex.Lock()
|
|
|
|
myCacheChosenGeneticAnalysisIdentifier = personAnalysisIdentifier
|
|
myCacheChosenGeneticAnalysis = myGeneticAnalysisObject
|
|
myCacheChosenGeneticAnalysis_GenomeIdentifierToUse = genomeIdentifierToUse
|
|
myCacheChosenGeneticAnalysis_MultipleGenomesExist = multipleGenomesExist
|
|
|
|
myChosenGeneticAnalysisCopy := myGeneticAnalysisObject
|
|
|
|
myCacheChosenGeneticAnalysisMutex.Unlock()
|
|
|
|
return true, true, true, myChosenGeneticAnalysisCopy, genomeIdentifierToUse, multipleGenomesExist, nil
|
|
}
|
|
|
|
|
|
//Outputs:
|
|
// -string: "Only Include Shared", "Only Exclude Conflicts"
|
|
// -error
|
|
func GetMyCombinedGenomeToUse()(string, error){
|
|
|
|
combinedGenomeToUseExists, combinedGenomeToUse, err := myLocalProfiles.GetProfileData("Mate", "CombinedGenomeToUse")
|
|
if (err != nil){ return "", err }
|
|
if (combinedGenomeToUseExists == false){
|
|
return "Only Exclude Conflicts", nil
|
|
}
|
|
|
|
if (combinedGenomeToUse != "Only Include Shared" && combinedGenomeToUse != "Only Exclude Conflicts"){
|
|
return "", errors.New("myLocalProfiles is malformed: Contains invalid combinedGenomeToUse: " + combinedGenomeToUse)
|
|
}
|
|
|
|
return combinedGenomeToUse, nil
|
|
}
|
|
|
|
|
|
func SetMyCombinedGenomeToUse(combinedGenomeToUse string)error{
|
|
|
|
if (combinedGenomeToUse != "Only Include Shared" && combinedGenomeToUse != "Only Exclude Conflicts"){
|
|
return errors.New("SetCombinedGenomeToUse called with invalid combinedGenomeToUse: " + combinedGenomeToUse)
|
|
}
|
|
|
|
err := myLocalProfiles.SetProfileData("Mate", "CombinedGenomeToUse", combinedGenomeToUse)
|
|
if (err != nil) { return err }
|
|
|
|
// We reset the global variables so the new analysis GenomeIdentifierToUse global variable will be updated
|
|
myCacheChosenGeneticAnalysisMutex.Lock()
|
|
|
|
myCacheChosenGeneticAnalysisIdentifier = ""
|
|
myCacheChosenGeneticAnalysis = geneticAnalysis.PersonAnalysis{}
|
|
myCacheChosenGeneticAnalysis_GenomeIdentifierToUse = [16]byte{}
|
|
myCacheChosenGeneticAnalysis_MultipleGenomesExist = false
|
|
|
|
myCacheChosenGeneticAnalysisMutex.Unlock()
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
|