private static MutationCategory LoadCategoryNode(XmlTextReader stream) { MutationCategory mutationCategory = new MutationCategory { Name = stream.GetAttribute("Name"), DisplayName = stream.GetAttribute("DisplayName"), Help = stream.GetAttribute("Help"), Stat = stream.GetAttribute("Stat"), Property = stream.GetAttribute("Property"), ForceProperty = stream.GetAttribute("ForceProperty") }; while (stream.Read()) { if (stream.Name == "mutation") { MutationEntry mutationEntry = Egcb_MutableMutations.LoadMutationNode(stream); mutationEntry.Category = mutationCategory; if (!mutationEntry.Prerelease || Options.GetOption("OptionEnablePrereleaseContent", string.Empty) == "Yes") { mutationCategory.Entries.Add(mutationEntry); } } if (stream.NodeType == XmlNodeType.EndElement && (stream.Name == string.Empty || stream.Name == "category")) { return(mutationCategory); } } return(mutationCategory); }
public double MutationRateForCategory(MutationCategory cat) { if (CountsByCategory.ContainsKey(cat)) { return(((double)CountsByCategory[cat]) / NumPossibleVariants); } else { return(0); } }
//Most of LoadVanillaMutations, LoadCategoryNode, and LoadMutationNode were adapted directly from the game's MutationFactory code private static void LoadVanillaMutations() { Egcb_MutableMutations.MutationData.Clear(); Egcb_MutableMutations.MutationCategoryDict.Clear(); using (XmlTextReader stream = DataManager.GetStreamingAssetsXMLStream("Mutations.xml")) { stream.WhitespaceHandling = WhitespaceHandling.None; while (stream.Read()) { if (stream.Name == "mutations") { while (stream.Read()) { if (stream.Name == "category") { MutationCategory mutationCategory = Egcb_MutableMutations.LoadCategoryNode(stream); if (mutationCategory.Name[0] == '-') { if (Egcb_MutableMutations.MutationCategoryDict.ContainsKey(mutationCategory.Name.Substring(1))) { MutationCategory cat = MutationFactory.CategoriesByName[mutationCategory.Name.Substring(1)]; Egcb_MutableMutations.MutationCategoryDict.Remove(mutationCategory.Name.Substring(1)); Egcb_MutableMutations.MutationData.Remove(cat); } } else if (Egcb_MutableMutations.MutationCategoryDict.ContainsKey(mutationCategory.Name)) { Egcb_MutableMutations.MutationCategoryDict[mutationCategory.Name].MergeWith(mutationCategory); } else { Egcb_MutableMutations.MutationCategoryDict.Add(mutationCategory.Name, mutationCategory); Egcb_MutableMutations.MutationData.Add(mutationCategory); } } if (stream.NodeType == XmlNodeType.EndElement && (stream.Name == string.Empty || stream.Name == "mutations")) { break; } } } if (stream.NodeType == XmlNodeType.EndElement && (stream.Name == string.Empty || stream.Name == "mutations")) { break; } } stream.Close(); } }
private Species GenerateInitialSpecies(EaterType eaterType, float calorieLimit) { List <Mutation> heads = AllMutations.Where(mutation => { HeadMutation head = mutation as HeadMutation; return(head != null && head.Type == eaterType); }).ToList(); List <Mutation> remainingMutations = AllMutations.Where(mutation => { return(!(mutation is HeadMutation) && !(mutation is TorsoMutation)); }).ToList(); Species newSpecies = new Species("Species"); newSpecies.AddMutation(_torsos[Random.Range(0, _torsos.Count)]); newSpecies.AddMutation(heads[Random.Range(0, heads.Count)]); while (remainingMutations.Count > 0 && newSpecies.CalorieConsumption < calorieLimit) { Mutation newMutation = remainingMutations[Random.Range(0, remainingMutations.Count)]; newSpecies.AddMutation(newMutation); for (int i = remainingMutations.Count - 1; i >= 0; i--) { MutationCategory category = remainingMutations[i].Category; if (category != null && category == newMutation.Category) { remainingMutations.RemoveAt(i); } } } newSpecies.OnResearchComplete += OnResearchComplete; Species.Add(newSpecies); BeginRandomResearch(newSpecies); return(newSpecies); }
/// <summary> /// This is a pretty naive reader. The mutation categories must be listed first, and the rates must be listed last, or the parsing fails. /// There are some hard coded strings. Yes, maybe it should be in json. /// </summary> /// <param name="file"></param> /// <returns></returns> public static CountData ReadCountsFile(string file) { CountData variantCounts = new CountData(); bool inRateSection = false; using (StreamReader sr = new StreamReader(new FileStream(file, FileMode.Open))) { string line; while (true) { line = sr.ReadLine(); if (line == "") { continue; } if (line == null) { break; } if (inRateSection) { string[] splat = line.Split(); if (splat.Length < 2) { continue; } double result = -1; if (!(double.TryParse(splat[1], out result))) { throw new IOException("Unable to parse counts from noise file " + file); } string firstWord = splat[0]; switch (firstWord) { case "AllPossibleVariants": variantCounts.NumPossibleVariants += result; break; case "FalsePosVariantsFound": case "ErrorRate(%)": case "VariantsCountedTowardEstimate": case "ErrorRateEstimate(%)": case "MismatchEstimate(%)": continue; default: //if its a mutation category - do something. Else do nothing if (MutationCategoryUtil.IsValidCategory(firstWord)) { MutationCategory category = MutationCategoryUtil.GetMutationCategory(firstWord); //this category should always exist. this is just defensive if (!variantCounts.CountsByCategory.ContainsKey(category)) { variantCounts.CountsByCategory.Add(category, 0); Logger.WriteWarningToLog("This counts file found a mutation category listed that this version of VQR is not aware of, and cannot process. Please check " + firstWord); } variantCounts.CountsByCategory[category] += result; } break; } } if (line.Contains("CountsByCategory")) { inRateSection = true; } } } return(variantCounts); }
public static void InsertNewQ(Dictionary <MutationCategory, int> qCalibratedRates, CalledAllele originalVar, MutationCategory cat, int newQ, bool isSomatic) { originalVar.VariantQscore = newQ; originalVar.NoiseLevelApplied = qCalibratedRates[cat]; if (isSomatic) { originalVar.GenotypeQscore = newQ; } }
public static void UpdateVariantQScoreAndRefilter(int maxQscore, int filterQScore, Dictionary <MutationCategory, int> qCalibratedRates, CalledAllele originalVar, MutationCategory cat, bool subsample) { double depth; double callCount; //tjd+ // We can revisit this math at a later date. Exactly how we lower the Qscores // or filter the suspect calls is TBD. We should work with this new algorithm // on a larger collection of datasets representing various alignment issues, // and modify the code/parameters as needed. // A few thoughts: Amplicon edge issues don't get better the deeper you sequence. // We need to scale out depth from the Q score calculation (since the original Q score is a fxn of depth/freq). // One option is to Cap at ~100 DP (TODO, this should be a parameter, a fxn of your bascallquality). // double subSampleToThis = 100; // tjd- double denominator = MathOperations.QtoP(qCalibratedRates[cat]); double subSampleToThis = 1.0 / denominator; if ((qCalibratedRates[cat] == 0) || (denominator == 0)) { subsample = false; } bool canUpdateQ = HaveInfoToUpdateQ(originalVar, out depth, out callCount); if (subsample && (depth > subSampleToThis)) { callCount = callCount * subSampleToThis / depth; depth = subSampleToThis; } if (canUpdateQ) { int newQ = VariantQualityCalculator.AssignPoissonQScore( (int)callCount, (int)depth, qCalibratedRates[cat], Math.Min(originalVar.VariantQscore, maxQscore)); //note, using "originalVar.VariantQscore" and the maxQ stops us from ever RAISING the q score over these values. InsertNewQ(qCalibratedRates, originalVar, cat, newQ, true); //update filters if needed if (newQ < filterQScore) { if (originalVar.Filters.Contains(FilterType.LowVariantQscore)) { return; } originalVar.Filters.Add(FilterType.LowVariantQscore); } } }
public static void InsertNewQ(Dictionary <MutationCategory, int> qCalibratedRates, VcfVariant originalVar, MutationCategory cat, int newQ) { originalVar.Quality = newQ; if (originalVar.Genotypes[0].ContainsKey("GQ")) { originalVar.Genotypes[0]["GQ"] = newQ.ToString(); } if (originalVar.Genotypes[0].ContainsKey("GQX")) { originalVar.Genotypes[0]["GQX"] = newQ.ToString(); } if (originalVar.Genotypes[0].ContainsKey("NL")) { originalVar.Genotypes[0]["NL"] = qCalibratedRates[cat].ToString(); } }
public static void UpdateVariant(int maxQscore, int filterQScore, Dictionary <MutationCategory, int> qCalibratedRates, VcfVariant originalVar, MutationCategory cat) { int depth; int callCount; bool canUpdateQ = HaveInfoToUpdateQ(originalVar, out depth, out callCount); if (canUpdateQ) { int newQ = VariantQualityCalculator.AssignPoissonQScore( callCount, depth, qCalibratedRates[cat], maxQscore); InsertNewQ(qCalibratedRates, originalVar, cat, newQ); //update filters if needed if (newQ < filterQScore) { var vcfConfig = new VcfWriterConfig(); vcfConfig.VariantQualityFilterThreshold = filterQScore; var formatter = new VcfFormatter(vcfConfig); string lowQString = formatter.MapFilter(FilterType.LowVariantQscore); string passString = VcfFormatter.PassFilter; if (originalVar.Filters.Contains(lowQString)) { return; } if (originalVar.Filters == passString) { originalVar.Filters = lowQString; } else { originalVar.Filters += VcfFormatter.FilterSeparator + lowQString; } } } }
public void LoadCountsFile(string file) { bool inRateSection = false; using (StreamReader sr = new StreamReader(file)) { string line; while (true) { line = sr.ReadLine(); if (line == "") { continue; } if (line == null) { break; } if (inRateSection) { string[] Splat = line.Split(); if (Splat.Length < 2) { continue; } double result = -1; if (!(double.TryParse(Splat[1], out result))) { throw new ApplicationException("Unable to parse counts from noise file " + file); } switch (Splat[0]) { case "AllPossibleVariants": NumPossibleVariants += result; break; case "FalsePosVariantsFound": case "ErrorRate(%)": case "VariantsCountedTowardEstimate": case "ErrorRateEstimate(%)": case "MismatchEstimate(%)": continue; default: MutationCategory category = MutationCounter.GetMutationCategory(Splat[0]); CountsByCategory[category] += result; break; } } if (line.Contains("CountsByCategory")) { inRateSection = true; } } } }