public TreeViaShape(double _x, double _y, double _thickness, double _height, double depth, double angle = 0, bool polygon = false, bool leaves = false) { if (leaves) { Line leaf = new Line(); leaf.Stroke = Brushes.Black; leaf.StrokeStartLineCap = PenLineCap.Round; leaf.StrokeEndLineCap = PenLineCap.Triangle; leaf.StrokeThickness = 2; leaf.X1 = _x; // + _thickness / 2 * Math.Cos(angle); leaf.Y1 = _y; // + _thickness / 2 * Math.Sin(angle); leaf.X2 = leaf.X1 + 5 * Math.Sin(angle); leaf.Y2 = leaf.Y1 - 5 * Math.Cos(angle); brunch = leaf; return; } if (polygon) { Polygon pol = new Polygon(); pol.Stroke = Brushes.Black; pol.Fill = Brushes.Black; pol.FillRule = FillRule.Nonzero; pol.Points.Add(new Point(_x, _y)); pol.Points.Add(new Point(_x + (1 - thick_coef) * _thickness / 2, _y - _height)); pol.Points.Add(new Point(_x + (1 + thick_coef) * _thickness / 2, _y - _height)); pol.Points.Add(new Point(_x + _thickness, _y)); if (angle > 0) { pol.RenderTransform = new RotateTransform(angle / rad2deg, _thickness, 0); } else { pol.RenderTransform = new RotateTransform(angle / rad2deg, 0, 0); } } else { brunch = new Rectangle(); brunch.Height = _height; brunch.Width = _thickness; brunch.Stroke = Brushes.Black; brunch.Fill = Brushes.Black; Canvas.SetLeft(brunch, _x); Canvas.SetTop(brunch, _y); //if (angle > 0) //brunch.RenderTransform = new RotateTransform(angle / rad2deg, // _thickness, // _height); //else brunch.RenderTransform = new RotateTransform(angle / rad2deg, 0, _height); } _thickness = _thickness * thick_coef; //_y -= _height; if (_height > 5 && depth < 350) { _x += _height * Math.Sin(angle) + ((brunch.Width - _thickness) / 2) * Math.Cos(angle); _y += _height * (1 - Math.Cos(angle)) - ((brunch.Width - _thickness) / 2) * Math.Sin(-angle); if (StaticRandom.NextDouble() < 0.9 || _thickness > 4) { center = new TreeViaShape(_x, _y - _height * height_coef, _thickness, _height * height_coef, depth + _height, angle, polygon); } if (StaticRandom.NextDouble() < 0.7 && (angle > -110 * rad2deg || _height < 15)) { double new_height = _height * StaticRandom.NextGaussian(0.8, 0.2, 0.3, 0.9); //double new_height = _height * StaticRandom.NextDouble(0.7, 0.9); left = new TreeViaShape(_x, _y - new_height, StaticRandom.NextDouble(_thickness * 0.6, _thickness * 0.9), new_height, depth + _height, angle - StaticRandom.NextDouble(10, 46) * rad2deg, polygon); } if (StaticRandom.NextDouble() < 0.7 && (angle < 110 * rad2deg || _height < 15)) { double new_height = _height * StaticRandom.NextGaussian(0.8, 0.2, 0.3, 0.9); //double new_height = _height * StaticRandom.NextDouble(0.7, 0.9); right = new TreeViaShape(_x, _y - new_height, StaticRandom.NextDouble(_thickness * 0.6, _thickness * 0.9), new_height, depth + _height, angle + StaticRandom.NextDouble(10, 46) * rad2deg, polygon); } } else { _x += _height * Math.Sin(angle) + (brunch.Width / 2) * Math.Cos(angle); _y += _height * (1 - Math.Cos(angle)) + (brunch.Width / 2) * Math.Sin(Math.Abs(angle)); center = new TreeViaShape(_x, _y, _thickness, _height, 0, angle, polygon, true); left = new TreeViaShape(_x - StaticRandom.NextDouble(_height / 5, _height / 2) * Math.Sin(angle), _y + StaticRandom.NextDouble(_height / 5, _height / 2) * Math.Cos(angle), _thickness, _height, 0, angle - StaticRandom.NextDouble(60, 90) * rad2deg, polygon, true); right = new TreeViaShape(_x - StaticRandom.NextDouble(_height / 5, _height / 2) * Math.Sin(angle), _y + StaticRandom.NextDouble(_height / 5, _height / 2) * Math.Cos(angle), _thickness, _height, 0, angle + StaticRandom.NextDouble(60, 90) * rad2deg, polygon, true); } }
public void GenerateProteins() { var angleInverseDistributions = LoadInverseAngleDistributions(); var pdbId = "1a2b"; var aminoAcidSequence = ReadAminoAcidSequenceFromPositionFile($@"G:\Projects\HumanGenome\Protein-PDBs\HumanProteins\AminoAcidPositions\pdb{pdbId}_model000.csv"); var distanceMapsDirectory = @"G:\Projects\HumanGenome\generatedProteins\DistanceMaps"; var positionFilesDirectory = @"G:\Projects\HumanGenome\generatedProteins\PositionFiles"; var distanceMean = 380; var distanceSigma = 4; var iterations = 1000; for (int iteration = 0; iteration < iterations; iteration++) { var aminoAcidPositions = new List <Point3D> { new Point3D(0, 0, 0) }; var lastAminoAcidLetter = aminoAcidSequence[0]; for (var aminoAcidIdx = 1; aminoAcidIdx < aminoAcidSequence.Count; aminoAcidIdx++) { var aminoAcidLetter = aminoAcidSequence[aminoAcidIdx]; var distance = StaticRandom.NextGaussian(distanceMean, distanceSigma); if (aminoAcidPositions.Count < 2) { aminoAcidPositions.Add(new Point3D(distance, 0, 0)); lastAminoAcidLetter = aminoAcidLetter; continue; } var angleInverseDistribution = angleInverseDistributions[lastAminoAcidLetter]; var angleInRadians = angleInverseDistribution.ValueAtX(StaticRandom.Rng.NextDouble()); var lastPosition = aminoAcidPositions.Last().To(SIPrefix.Pico, Unit.Meter); var vector1 = aminoAcidPositions[aminoAcidIdx - 2].VectorTo(aminoAcidPositions[aminoAcidIdx - 1]); var vector2 = aminoAcidIdx >= 3 ? aminoAcidPositions[aminoAcidIdx - 3].VectorTo(aminoAcidPositions[aminoAcidIdx - 2]) : new Vector3D(0, 1, 0); var bestPositionedPoint = ApproximateAminoAcidPositioner.CalculateAtomPosition( lastPosition, vector1, vector2, distance.To(SIPrefix.Pico, Unit.Meter), angleInRadians.To(Unit.Radians), (2 * Math.PI * (StaticRandom.Rng.NextDouble() - 0.5)).To(Unit.Radians)); var isColliding = CollidesWithExistingPositions(bestPositionedPoint, aminoAcidPositions, out var distanceToClosest); var bestDistanceToClosest = distanceToClosest; const int MaxPositionIterations = 3; var positionIteration = 0; while (isColliding && positionIteration < MaxPositionIterations) { positionIteration++; var pointCandidate = ApproximateAminoAcidPositioner.CalculateAtomPosition( lastPosition, vector1, vector2, distance.To(SIPrefix.Pico, Unit.Meter), angleInRadians.To(Unit.Radians), (2 * Math.PI * (StaticRandom.Rng.NextDouble() - 0.5)).To(Unit.Radians)); isColliding = CollidesWithExistingPositions(bestPositionedPoint, aminoAcidPositions, out distanceToClosest); if (!isColliding) { bestPositionedPoint = pointCandidate; break; } if (distanceToClosest > bestDistanceToClosest) { bestPositionedPoint = pointCandidate; bestDistanceToClosest = distanceToClosest; } } aminoAcidPositions.Add(bestPositionedPoint.In(SIPrefix.Pico, Unit.Meter)); lastAminoAcidLetter = aminoAcidLetter; } var filenameBase = $"pdb{pdbId}_gen{iteration}"; var distanceMap = DistanceMapGenerator.Generate(aminoAcidPositions); distanceMap.Save(Path.Combine(distanceMapsDirectory, filenameBase + ".png")); File.WriteAllLines( Path.Combine(positionFilesDirectory, filenameBase + ".csv"), Enumerable.Range(0, aminoAcidSequence.Count) .Select(idx => $"{aminoAcidSequence[idx]};{aminoAcidPositions[idx].ToString()}")); } }
public void MakeATree(double _x, double _y, double _thickness, double _height, double depth, double angle = 0, bool polygon = false, bool leaves = false) { if (leaves) { EllipseGeometry leaf = new EllipseGeometry(new Point(_x, _y), leafHOR, leafVER); leaf.Transform = new RotateTransform(angle / rad2deg, _x, _y); tree.Children.Add(leaf); double new_x = _x - StaticRandom.NextDouble(_height / 5, _height / 2) * Math.Sin(angle); double new_y = _y + StaticRandom.NextDouble(_height / 5, _height / 2) * Math.Cos(angle); leaf = new EllipseGeometry(new Point(new_x, new_y), leafHOR, leafVER); leaf.Transform = new RotateTransform(angle / rad2deg + 90, new_x, new_y); tree.Children.Add(leaf); new_x = _x - StaticRandom.NextDouble(_height / 5, _height / 2) * Math.Sin(angle); new_y = _y + StaticRandom.NextDouble(_height / 5, _height / 2) * Math.Cos(angle); leaf = new EllipseGeometry(new Point(new_x, new_y), leafHOR, leafVER); leaf.Transform = new RotateTransform(angle / rad2deg - 90, new_x, new_y); tree.Children.Add(leaf); return; } if (polygon) { StreamGeometry a = new StreamGeometry(); using (var b = a.Open()) { b.BeginFigure(new Point(_x, _y + _height), true, true); b.LineTo(new Point(_x + (1 - thick_coef) * _thickness / 2, _y), true, true); b.LineTo(new Point(_x + (1 + thick_coef) * _thickness / 2, _y), true, true); b.LineTo(new Point(_x + _thickness, _y + _height), true, true); b.Close(); } a.Transform = new RotateTransform(angle / rad2deg, _x, _y + _height); tree.Children.Add(a); } else { Rect rectangle = new Rect(new Point(_x, _y), new Size(_thickness, _height)); RectangleGeometry brunch = new RectangleGeometry(rectangle); if (angle > 0) { brunch.Transform = new RotateTransform(angle / rad2deg, _x + _thickness, _y + _height); } else { brunch.Transform = new RotateTransform(angle / rad2deg, _x, _y + _height); } tree.Children.Add(brunch); } //_y -= _height; if (_height > 5 && depth < 350) { _x += _height * Math.Sin(angle) + (1 - thick_coef) * _thickness / 2 * Math.Cos(angle); _y += _height * (1 - Math.Cos(angle)) - (1 - thick_coef) * _thickness / 2 * Math.Sin(-angle); _thickness = _thickness * thick_coef; if (StaticRandom.NextDouble() < 0.9 || _thickness > 4) { double new_height = _height * StaticRandom.NextGaussian(0.85, 0.1, 0.7, 1); MakeATree(_x, _y - new_height, _thickness, new_height, depth + _height, angle, polygon); } if (StaticRandom.NextDouble() < 0.7 && (angle > -110 * rad2deg || _height < 15)) { double new_height = _height * StaticRandom.NextGaussian(0.8, 0.2, 0.3, 0.9); //double new_height = _height * StaticRandom.NextDouble(0.7, 0.9); MakeATree(_x, _y - new_height, StaticRandom.NextDouble(_thickness * 0.6, _thickness * 0.9), new_height, depth + _height, angle - StaticRandom.NextDouble(10, 46) * rad2deg, polygon); } if (StaticRandom.NextDouble() < 0.7 && (angle < 110 * rad2deg || _height < 15)) { double new_height = _height * StaticRandom.NextGaussian(0.8, 0.2, 0.3, 0.9); //double new_height = _height * StaticRandom.NextDouble(0.7, 0.9); MakeATree(_x, _y - new_height, StaticRandom.NextDouble(_thickness * 0.6, _thickness * 0.9), new_height, depth + _height, angle + StaticRandom.NextDouble(10, 46) * rad2deg, polygon); } } else { _x += _height * Math.Sin(angle) + thick_coef * _thickness / 2 * Math.Cos(angle); _y += _height * (1 - Math.Cos(angle)) + thick_coef * _thickness / 2 * Math.Sin(Math.Abs(angle)); MakeATree(_x, _y, _thickness, _height, 0, angle, polygon, true); } return; }