public CrossTrait(List<Trait> p_traits, double p_rate, bool m = true, bool f = true) { this.rate = p_rate; this.trait = p_traits.ElementAt(0); this.dist_traits = p_traits; this.male = m; this.female = f; this.used = 0; this.distance_based = true; }
public CrossTrait(Trait p_trait, double p_rate, bool m = true, bool f = true) { this.rate = p_rate; this.trait = p_trait; this.dist_traits = null; this.male = m; this.female = f; this.used = 0; this.distance_based = false; }
public ReducedTraitModel(Trait t) { this.Id = t.Id; this.ChromosomeNumber = t.ChromosomeNumber; this.CategoryId = t.CategoryId; this.Distance = t.Distance; this.Name = t.Name; this.ImagePath = t.ImagePath; this.IsHeterozygous = t.IsHeterozygous ?? false; this.IsDominant = t.IsDominant; this.IsIncompleteDominant = t.IsIncompleteDominant; this.IsLethal = t.IsLethal; }
/// <summary> /// Returns an aray of trait possibilites and their spawn percentages. /// Bad data/data that does not obey the algorithm will cause hilarious (read: annoying) /// bugs. Make sure the user is forced to follow the rules rigidly. /// </summary> /// <param name="p_fatherTraits">Father's traits</param> /// <param name="p_motherTraits">Mother's traits</param> /// <returns></returns> private CrossList ThreePointCross(ReducedTraitModel[] p_fatherTraits, ReducedTraitModel[] p_motherTraits) { //FIX ORDER p_fatherTraits = p_fatherTraits.OrderBy(t => t.Distance).ToArray(); p_motherTraits = p_motherTraits.OrderBy(t => t.Distance).ToArray(); List<CrossTrait> returnArr = new List<CrossTrait>(); #region Trait_Prep //generate wild, het, hom for each trait & gender Trait[] wild = new Trait[3]; Trait[] hets = new Trait[3]; Trait[] homs = new Trait[3]; Trait[] father_raw = new Trait[3]; Trait[] mother_raw = new Trait[3]; for (int i = 0; i < 3; i++) { Trait dbTrt1 = db.Trait.Find(p_fatherTraits[i].Id); Trait dbTrt2 = db.Trait.Find(p_motherTraits[i].Id); wild[i] = db.Trait.FirstOrDefault(t => t.CategoryId == dbTrt1.CategoryId && t.Name.ToLower() == Constants.Wild.ToLower()); hets[i] = GetTrait((dbTrt1.Name != Constants.Wild) ? dbTrt1 : dbTrt2, true); homs[i] = GetTrait((dbTrt1.Name != Constants.Wild) ? dbTrt1 : dbTrt2, false); } #endregion #region Distance_Linked //check father trait, then mother trait to determine case List<Trait> building = new List<Trait>(); if ((!p_fatherTraits[0].IsHeterozygous && !p_fatherTraits[1].IsHeterozygous && !p_fatherTraits[2].IsHeterozygous) && (!p_motherTraits[0].IsHeterozygous && !p_motherTraits[1].IsHeterozygous && !p_motherTraits[2].IsHeterozygous)) { //father hom-hom, mother hom-hom //one output: het-het building.Add(hets[0]); building.Add(hets[1]); building.Add(hets[2]); returnArr.Add(new CrossTrait(building, 1)); return FinishCross(returnArr, 1); } else { //2 traits must be heterozygous by necessity of the algorithm //calculate recombinance rates double dist1 = (p_fatherTraits[0].Name != Constants.Wild) ? p_fatherTraits[0].Distance : p_motherTraits[0].Distance; double dist2 = (p_fatherTraits[1].Name != Constants.Wild) ? p_fatherTraits[1].Distance : p_motherTraits[1].Distance; double dist3 = (p_fatherTraits[2].Name != Constants.Wild) ? p_fatherTraits[2].Distance : p_motherTraits[2].Distance; //TODO CHANGE!! double recombined_rate_1_2 = Math.Abs(dist1 - dist2) / 100; double unrecombined_rate_1_2 = 1 - recombined_rate_1_2; double recombined_rate_2_3 = Math.Abs(dist2 - dist3) / 100; double unrecombined_rate_2_3 = 1 - recombined_rate_2_3; #region no_recombine building = new List<Trait>(); building.Add(homs[0]); building.Add(homs[1]); building.Add(homs[2]); returnArr.Add(new CrossTrait(building, (unrecombined_rate_1_2 * unrecombined_rate_2_3))); building = new List<Trait>(); building.Add(hets[0]); building.Add(hets[1]); building.Add(hets[2]); returnArr.Add(new CrossTrait(building, (unrecombined_rate_1_2 * unrecombined_rate_2_3))); #endregion #region single_recombine building = new List<Trait>(); building.Add(homs[0]); building.Add(hets[1]); building.Add(hets[2]); returnArr.Add(new CrossTrait(building, (recombined_rate_1_2 * unrecombined_rate_2_3))); building = new List<Trait>(); building.Add(hets[0]); building.Add(hets[1]); building.Add(homs[2]); returnArr.Add(new CrossTrait(building, (unrecombined_rate_1_2 * recombined_rate_2_3))); building = new List<Trait>(); building.Add(homs[0]); building.Add(homs[1]); building.Add(hets[2]); returnArr.Add(new CrossTrait(building, (unrecombined_rate_1_2 * recombined_rate_2_3))); building = new List<Trait>(); building.Add(hets[0]); building.Add(homs[1]); building.Add(homs[2]); returnArr.Add(new CrossTrait(building, (recombined_rate_1_2 * unrecombined_rate_2_3))); #endregion #region double_recombine building = new List<Trait>(); building.Add(hets[0]); building.Add(homs[1]); building.Add(hets[2]); returnArr.Add(new CrossTrait(building, (recombined_rate_1_2 * recombined_rate_2_3))); building = new List<Trait>(); building.Add(homs[0]); building.Add(hets[1]); building.Add(homs[2]); returnArr.Add(new CrossTrait(building, (recombined_rate_1_2 * recombined_rate_2_3))); #endregion return FinishCross(returnArr, 8); } #endregion /* THERE ARE 4 POSSIBLE CASES * 1: NO RECOMBINE * 2: T1T2 RECOMBINE * 3: T1T2T3 RECOMBINE * 4: T2T3 RECOMBINE */ //return new CrossList(); }
/// <summary> /// Build a new trait object from an existing trait /// </summary> /// <param name="t">Trait to copy</param> /// <param name="isHet">Heterozygosity of new trait</param> /// <returns></returns> private Trait GetTrait(Trait t, bool isHet) { return new Trait() { Id = t.Id, Category = t.Category, CategoryId = t.CategoryId, ChromosomeNumber = t.ChromosomeNumber, Distance = t.Distance, IsDominant = t.IsDominant, IsHeterozygous = isHet, IsLethal = t.IsLethal, Name = t.Name, IsIncompleteDominant = t.IsIncompleteDominant, ImagePath = t.ImagePath }; }
/// <summary> /// Returns an array of trait possibilities and their spawn percentages /// based on the provided trait pair /// </summary> /// <param name="p_fatherTrait">Father's trait</param> /// <param name="p_motherTrait">Mother's Trait</param> /// <returns>The processed list of child possibilities</returns> private CrossList BasicCross(ReducedTraitModel p_fatherTrait, ReducedTraitModel p_motherTrait) { Trait dbTrt1 = db.Trait.Find(p_fatherTrait.Id); Trait dbTrt2 = db.Trait.Find(p_motherTrait.Id); Trait trait1 = new Trait(); Trait trait2 = new Trait(); List<CrossTrait> returnArr = new List<CrossTrait>(); int count = 0; #region Sex_Linked if (dbTrt1.ChromosomeNumber == 1 || dbTrt2.ChromosomeNumber == 1) { #region Sex_Trait_Prep //take in traits after detecting that they are sex linked (on chromosome 1) //make special sex trait and perform cross //parse it in children method //?????? //profit //make trait1 heterozygous (Male XY) and trait2 homozygous (Female XX) trait1 = new Trait() { Id = dbTrt1.Id, Name = Constants.SexLinked, Father = GetTrait(dbTrt1, p_fatherTrait.IsHeterozygous), Mother = GetTrait(dbTrt2, p_motherTrait.IsHeterozygous), IsHeterozygous = true, ChromosomeNumber = 1, CategoryId = dbTrt1.CategoryId }; trait2 = new Trait() { Id = dbTrt2.Id, Name = Constants.SexLinked, Father = GetTrait(dbTrt1, p_fatherTrait.IsHeterozygous), Mother = GetTrait(dbTrt2, p_motherTrait.IsHeterozygous), IsHeterozygous = false, ChromosomeNumber = 1, CategoryId = dbTrt2.CategoryId }; //do some fancy processing and abuse CrossTrait's new Male and Female bools //we know the list contains a sex-linked trait, so find it Trait sexLinkedTrait = dbTrt1.ChromosomeNumber == 1 ? trait1 : trait2; Trait hetFatherTrait = GetTrait(sexLinkedTrait.Father, true); Trait homFatherTrait = GetTrait(sexLinkedTrait.Father, false); Trait hetMotherTrait = GetTrait(sexLinkedTrait.Mother, true); Trait homMotherTrait = GetTrait(sexLinkedTrait.Mother, false); #endregion if (sexLinkedTrait.Mother.ChromosomeNumber == 1 && sexLinkedTrait.Father.ChromosomeNumber == 1) { //we know they will be the same trait, so there are only 2 cross cases here... if (sexLinkedTrait.Mother.IsHeterozygous ?? false) { //het - hemi cross Trait wildTrait = db.Trait.First(t => t.CategoryId == sexLinkedTrait.Father.ChromosomeNumber && t.Name.ToLower() == Constants.Wild.ToLower()); returnArr.Add(new CrossTrait(homMotherTrait, .5, false, true)); //aff female returnArr.Add(new CrossTrait(hetMotherTrait, .5, false, true)); //carrier female returnArr.Add(new CrossTrait(homMotherTrait, .5, true, false)); //aff male returnArr.Add(new CrossTrait(wildTrait , .5, true, false)); //unaff male count = 4; return FinishCross(returnArr, count); } else { //hom - hemi cross returnArr.Add(new CrossTrait(homMotherTrait, 1, true, false)); //aff male returnArr.Add(new CrossTrait(homMotherTrait, 1, false, true)); //aff female count = 2; return FinishCross(returnArr, count); } } if (sexLinkedTrait.Father.ChromosomeNumber == 1) { //affected father if (!(sexLinkedTrait.Mother.IsHeterozygous ?? false)) { returnArr.Add(new CrossTrait(hetFatherTrait, 1, false, true)); //carrier females returnArr.Add(new CrossTrait(homMotherTrait, 1, true, false)); //unaff males count = 2; return FinishCross(returnArr, count); } } else { //affected mother if (sexLinkedTrait.Mother.IsHeterozygous ?? false) { //hetrec sex linked //1 son wild, 1 son aff, 1 daughter wild, 1 daughter het returnArr.Add(new CrossTrait(hetMotherTrait, .5, false, true)); //carrier female returnArr.Add(new CrossTrait(homFatherTrait, .5, false, true)); //unaff female returnArr.Add(new CrossTrait(homMotherTrait, .5, true, false)); //aff male returnArr.Add(new CrossTrait(homFatherTrait, .5, true, false)); //unaff male count = 4; return FinishCross(returnArr, count); } else { returnArr.Add(new CrossTrait(hetMotherTrait, 1, false, true)); //carrier females returnArr.Add(new CrossTrait(homMotherTrait, 1, true, false)); //aff males count = 2; return FinishCross(returnArr, count); } } } #endregion #region Non_Sex_Linked else { #region Trait_Prep trait1 = GetTrait(dbTrt1, p_fatherTrait.IsHeterozygous); trait2 = GetTrait(dbTrt2, p_motherTrait.IsHeterozygous); #endregion } //het-het if ((trait1.IsHeterozygous ?? false) && (trait2.IsHeterozygous ?? false)) { //we know theyre same trait so we return accordingly Trait wildTrait = db.Trait.First(t => t.Name.ToLower() == Constants.Wild.ToLower() && t.CategoryId == trait1.CategoryId); Trait homTrait = GetTrait(trait1, false); Trait hetTrait = GetTrait(trait1, true); returnArr.Add(new CrossTrait(homTrait, .25)); returnArr.Add(new CrossTrait(hetTrait, .5)); returnArr.Add(new CrossTrait(wildTrait, .25)); count = 3; return FinishCross(returnArr, count); } //hom-hom if (!(trait1.IsHeterozygous ?? false) && !(trait2.IsHeterozygous ?? false)) { if (trait1.Name.ToLower() == Constants.Wild.ToLower() && trait2.Name.ToLower() == Constants.Wild.ToLower()) { returnArr.Add(new CrossTrait(trait1, 1)); count = 1; return FinishCross(returnArr, count); } //rec-wild else if (!trait1.IsDominant && trait2.Name.ToLower() == Constants.Wild.ToLower()) { Trait expressed = trait1; expressed.IsHeterozygous = true; returnArr.Add(new CrossTrait(expressed, 1)); count = 1; return FinishCross(returnArr, count); } //wild-rec else if (!trait2.IsDominant && trait1.Name.ToLower() == Constants.Wild.ToLower()) { Trait expressed = trait2; expressed.IsHeterozygous = true; returnArr.Add(new CrossTrait(expressed, 1)); count = 1; return FinishCross(returnArr, count); } //dom-rec* else if (trait1.IsDominant) { Trait expressed = trait1; expressed.IsHeterozygous = true; returnArr.Add(new CrossTrait(expressed, 1)); count = 1; return FinishCross(returnArr, count); } else if (trait2.IsDominant) { Trait expressed = trait2; expressed.IsHeterozygous = true; returnArr.Add(new CrossTrait(expressed, 1)); count = 1; return FinishCross(returnArr, count); } } //hom-het if ((!(trait1.IsHeterozygous ?? false) && (trait2.IsHeterozygous ?? false)) || (!(trait2.IsHeterozygous ?? false) && (trait1.IsHeterozygous ?? false))) { Trait homTrait = (trait1.IsHeterozygous ?? false) ? trait2 : trait1; Trait hetTrait = (trait1.IsHeterozygous ?? false) ? trait1 : trait2; returnArr.Add(new CrossTrait(hetTrait, .5)); returnArr.Add(new CrossTrait(homTrait, .5)); count = 2; return FinishCross(returnArr, count); } #endregion return new CrossList(); }
/// <summary> /// Returns an aray of trait possibilites and their spawn percentages. /// Bad data/data that does not obey the algorithm will cause hilarious (read: annoying) /// bugs. Make sure the user is forced to follow the rules rigidly. /// </summary> /// <param name="p_fatherTraits">Father's traits</param> /// <param name="p_motherTraits">Mother's traits</param> /// <returns></returns> private CrossList TwoPointCross(ReducedTraitModel[] p_fatherTraits, ReducedTraitModel[] p_motherTraits) { List<CrossTrait> returnArr = new List<CrossTrait>(); #region Trait_Prep //generate wild, het, hom for each trait & gender Trait[] wild = new Trait[2]; Trait[] father_hets = new Trait[2]; Trait[] father_homs = new Trait[2]; Trait[] mother_hets = new Trait[2]; Trait[] mother_homs = new Trait[2]; Trait[] father_raw = new Trait[2]; Trait[] mother_raw = new Trait[2]; for (int i = 0; i < 2; i++) { Trait dbTrt1 = db.Trait.Find(p_fatherTraits[i].Id); Trait dbTrt2 = db.Trait.Find(p_motherTraits[i].Id); wild[i] = db.Trait.FirstOrDefault(t => t.CategoryId == dbTrt1.CategoryId && t.Name.ToLower() == Constants.Wild.ToLower()); //father modified father_hets[i] = GetTrait(dbTrt1, true); father_homs[i] = GetTrait(dbTrt1, false); //mother modified mother_hets[i] = GetTrait(dbTrt2, true); mother_homs[i] = GetTrait(dbTrt2, false); //raw arrays father_raw[i] = GetTrait(dbTrt1, p_fatherTraits[i].IsHeterozygous); mother_raw[i] = GetTrait(dbTrt2, p_motherTraits[i].IsHeterozygous); } #endregion #region Distance_Linked //check father trait, then mother trait to determine case List<Trait> building = new List<Trait>(); if ((!p_fatherTraits[0].IsHeterozygous && !p_fatherTraits[1].IsHeterozygous) && (!p_motherTraits[0].IsHeterozygous && !p_motherTraits[1].IsHeterozygous)) { //father hom-hom, mother hom-hom //one output: het-het building.Add((father_hets[0].Name != Constants.Wild) ? father_hets[0] : mother_hets[0]); building.Add((father_hets[1].Name != Constants.Wild) ? father_hets[1] : mother_hets[1]); returnArr.Add(new CrossTrait(building, 1)); return FinishCross(returnArr, 1); } else { //2 traits must be heterozygous by necessity of the algorithm //calculate recombinance rates double dist1 = (p_fatherTraits[0].Name != Constants.Wild) ? father_raw[0].Distance : mother_raw[0].Distance; double dist2 = (p_fatherTraits[1].Name != Constants.Wild) ? father_raw[1].Distance : mother_raw[1].Distance; double recombined_rate = Math.Abs(dist1 - dist2) / 100; double unrecombined_rate = 1 - recombined_rate; //build all four possibilities building.Add(father_raw[0]); building.Add(father_raw[1]); //unrecombined returnArr.Add(new CrossTrait(building, unrecombined_rate / 2)); building = new List<Trait>(); building.Add(mother_raw[0]); building.Add(mother_raw[1]); //unrecombined returnArr.Add(new CrossTrait(building, unrecombined_rate / 2)); building = new List<Trait>(); building.Add(mother_raw[0]); building.Add(father_raw[1]); //recombined returnArr.Add(new CrossTrait(building, recombined_rate / 2)); building = new List<Trait>(); building.Add(father_raw[0]); building.Add(mother_raw[1]); //recombined returnArr.Add(new CrossTrait(building, recombined_rate / 2)); return FinishCross(returnArr, 4); } #endregion //return new CrossList(); }
public ActionResult CreateCat(Category category) { if (category.Id == 0) { if (db.Category.Count(t => t.CatName.ToLower().Equals(category.CatName.ToLower())) != 0) { return RedirectToAction("Categories"); } db.Category.Add(category); //we also need a wild trait for this category Trait wild = new Trait() { Id = 0, Category = category, CategoryId = category.Id, ChromosomeNumber = 0, Distance = 200, IsDominant = false, IsIncompleteDominant = false, IsLethal = false, Name = Constants.Wild, ImagePath = Constants.Wild }; db.Trait.Add(wild); try { db.SaveChanges(); return RedirectToAction("Categories"); } catch (Exception e) { Exception ex = new InvalidOperationException("There was an issue adding category " + category.CatName + ".", e); Elmah.ErrorSignal.FromCurrentContext().Raise(ex); return View(category); } } else { if (ModelState.IsValid) { db.Entry(category).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Categories"); } } return View(category); }
public ActionResult Edit(Trait trait) { try { //new trait if (trait.Id == 0 && trait.Name.ToLower() != Constants.Wild.ToLower()) { if (!trait.IsDominant) { trait.IsIncompleteDominant = false; } db.Trait.Add(trait); try { db.SaveChanges(); return RedirectToAction("Traits"); } catch (Exception e) { Elmah.ErrorSignal.FromCurrentContext().Raise(e); ViewBag.CategoryId = new SelectList(db.Category, "Id", "CatName", trait.CategoryId); return View("Create", trait); } } //old trait else if (ModelState.IsValid) { Trait existing = db.Trait.Find(trait.Id); if (existing.Name.ToLower() == Constants.Wild.ToLower()) { //we cant allow anything but imagepath to be changed existing.ImagePath = trait.ImagePath; } else { existing.Name = trait.Name; existing.Category = trait.Category; existing.CategoryId = trait.CategoryId; existing.ChromosomeNumber = trait.ChromosomeNumber; existing.Distance = trait.Distance; existing.Flies = trait.Flies; existing.ImagePath = trait.ImagePath; existing.IsDominant = trait.IsDominant; existing.IsHeterozygous = trait.IsHeterozygous; existing.IsIncompleteDominant = (trait.IsDominant) ? trait.IsIncompleteDominant : false; existing.IsLethal = trait.IsLethal; } db.Entry(existing).State = EntityState.Modified; try { db.SaveChanges(); return RedirectToAction("Traits"); } catch (Exception e) { Elmah.ErrorSignal.FromCurrentContext().Raise(e); return RedirectToAction("InternalError", "Error"); } } } catch (Exception e) { Elmah.ErrorSignal.FromCurrentContext().Raise(e); } //failed trait ViewBag.CategoryId = new SelectList(db.Category, "Id", "CatName", trait.CategoryId); return View("Create", trait); }