public static string WriteMolString(Molecule mol) { //First we write to a temp file, we then open the file, read all of the text and return it as a string WriteMolFile("writertemp.mol", mol); string molString = File.ReadAllText("writertemp.mol"); //Now we delete the temp file File.Delete("writertemp.mol"); return molString; }
public static void ReadMolFile(string filePath, ref Molecule mol) { using (StreamReader reader = File.OpenText(filePath)) { ParseHeaderBlock(reader, ref mol); ParseCountsLine(reader, ref mol); ParseAtomBlock(reader, ref mol); ParseBondBlock(reader, ref mol); ParsePropertiesBlock(reader, ref mol); } }
public static void WriteMolFile(string filePath, Molecule mol) { using (StreamWriter writer = File.CreateText(filePath)) { WriteHeaderBlock(writer, mol); WriteCountsLine(writer, mol); WriteAtomBlock(writer, mol); WriteBondBlock(writer, mol); writer.WriteLine("M END"); } }
public static void ReadMolData(string text, ref Molecule mol) { StringBuilder builder = new StringBuilder(text); System.Text.ASCIIEncoding encode = new ASCIIEncoding(); byte[] byteArray = encode.GetBytes(text); using (Stream s = new MemoryStream(byteArray)) { using (StreamReader reader = new StreamReader(s)) { ParseHeaderBlock(reader, ref mol); ParseCountsLine(reader, ref mol); ParseAtomBlock(reader, ref mol); ParseBondBlock(reader, ref mol); ParsePropertiesBlock(reader, ref mol); } } }
private static void WriteAtomBlock(StreamWriter writer, Molecule mol) { //It goes xxxxx.xxxxyyyyy.yyyyzzzzz.zzzz aaaddcccssshhhbbbvvvHHHrrriiimmmnnneee for each atom foreach (Node atom in mol.Atoms.Values) { string line = string.Empty; string x = atom.Position.X.ToString(); if (atom.Position.X == Math.Round(atom.Position.X)) //is it an intergral # x += ".0000"; x = x.PadLeft(10, ' '); //pad left so we get 10 chars line += x; string y = atom.Position.Y.ToString(); if (atom.Position.Y == Math.Round(atom.Position.Y)) y += ".0000"; y = y.PadLeft(10, ' '); line += y; string z = string.Empty; if (atom.Position.Z == 0 || Math.Round(atom.Position.Z) == atom.Position.Z) z = atom.Position.Z.ToString() + ".0000"; else z = atom.Position.Z.ToString(); z = z.PadLeft(10); line += z + " "; //one extra space after coords //next is atom sybmol string symbol = atom.Symbol; symbol = symbol.PadRight(4); line += symbol; line += "0 "; //mass difference is skipped //Next part is the charge line += atom.Charge + " "; //next parity which is skipped line += "0 "; //next is hydrogen count line += atom.RequiredHydrogens + " "; //skip next line += "0 "; //finally valence line += atom.Valence + " 0 0 0 0 0 0"; writer.WriteLine(line); } }
private static void WriteBondBlock(StreamWriter writer, Molecule mol) { // 111222tttsssxxxrrrccc first atom # second atom # bond type bond stereo foreach (Bond bond in mol.Bonds) { Console.WriteLine("MolFileWriter.WriteBondBlock: atom {0} connected to atom {1}", bond.Node1.ID, bond.Node2.ID); string line = string.Empty; string atom1 = bond.Node1.ID.ToString(); atom1 = atom1.PadLeft(3, ' '); line += atom1; string atom2 = bond.Node2.ID.ToString(); atom2 = atom2.PadLeft(3, ' '); line += atom2; string order = bond.BondOrder.ToString(); order = order.PadLeft(3, ' '); line += order; string stereo = bond.BondStereo.ToString(); stereo = stereo.PadLeft(3, ' '); line += stereo; //For now we skip topology and reaction center status line += " 0 0 0"; writer.WriteLine(line); } }
private static void ParseAtomBlock(StreamReader reader, ref Molecule mol) { //It goes xxxxx.xxxxyyyyy.yyyyzzzzz.zzzz aaaddcccssshhhbbbvvvHHHrrriiimmmnnneee for each atom //From the counts line we know how many atoms to expect for (int i = 1; i <= mol.NumberOfAtoms; i++) { string line = reader.ReadLine(); //First the coords Node atomToAdd = new Node(); double x, y, z; bool result = double.TryParse(line.Substring(0, 10), out x); if (!result) Console.WriteLine("Could not parse x coords"); result = double.TryParse(line.Substring(10, 10), out y); if (!result) Console.WriteLine("Could not parse y coords"); result = double.TryParse(line.Substring(20,10), out z); if (!result) Console.WriteLine("Could not parse z coords"); if (z == 0) z = 0.0000; Vector3 coords = new Vector3(x, y, z); atomToAdd.Position = coords; //Next we split the string into parts and the 3rd entry is the atomic symbol string[] delim = { " " }; string[] parts = line.Split(delim, StringSplitOptions.RemoveEmptyEntries); atomToAdd.Symbol = parts[3]; //The fourth is mass difference ?!?!? NOT added int massDifference; result = int.TryParse(parts[4], out massDifference); if (!result) Console.WriteLine("Could not parse mass difference"); else atomToAdd.MassDiff = massDifference; //The fifth is charge int charge; result = int.TryParse(parts[5], out charge); if (!result) Console.WriteLine("Could not parse atomic charge"); else { atomToAdd.Charge = charge; Console.WriteLine("ATOM " + atomToAdd.Symbol + " CHARGE " + charge); } //The sixth is atom stereo parity which is ignored //The seventh is hydrogen count int hCount; result = int.TryParse(parts[7], out hCount); if (!result) Console.WriteLine("Could not parse hydrogen count"); else { if (hCount > 0) Console.WriteLine("hcount above 0"); Console.WriteLine("ATOM " + atomToAdd.Symbol + " HS " + hCount); atomToAdd.RequiredHydrogens = hCount; } //Stereo care box is skipped //The ninth is valence 0 = no marking default, includes number of bonds on this atom including implied //hydrogens int valence; result = int.TryParse(parts[9], out valence); if (!result) Console.WriteLine("Could not parse valence"); else atomToAdd.Valence = valence; atomToAdd.ID = i; //finally we add the atom to the list mol.Atoms.Add(i, atomToAdd); } }
private static void WriteHeaderBlock(StreamWriter writer, Molecule mol) { //Line 1 : molecule name, can be blank, no longer than 80 letters writer.WriteLine(mol.Name); /*Line 2: IIPPPPPPPPMMDDYYHHmmddSSssssssssssEEEEEEEEEEEERRRRRR *User's first and last initials (l), program name (P), *date/time (M/D/Y,H:m), dimensional codes (d), scaling factors (S, s), * energy (E) if modeling program input, * internal registry number (R) if input through MDL form. * can be blank */ string line2 = string.Empty; if (mol.CreatedBy.Length == 2) line2 += mol.CreatedBy; else line2 += " "; //no initials means two spaces added //The program is eight chars so we check our program name (generally SynType or ChemDraw) string buildSoft = mol.BuildSoftware; buildSoft = buildSoft.PadRight(8, ' '); line2 += buildSoft; //The next is the date string month; //month is not always 2 digits so we make sure it is if (mol.CreationTime.Month < 10) { month = mol.CreationTime.Month.ToString(); month = month.PadLeft(2, '0'); } else month = mol.CreationTime.Month.ToString(); string day; //day is also not always 2 digits so we pad as well if (mol.CreationTime.Day < 10) { day = mol.CreationTime.Day.ToString(); day = day.PadLeft(2, '0'); } else day = mol.CreationTime.Day.ToString(); int year = mol.CreationTime.Year; int hour = mol.CreationTime.Hour; int min = mol.CreationTime.Minute; Console.WriteLine("MolFileWriter: DT {0}/{1}/{2} {3}:{4}", day, month, year, hour, min); line2 += month + day + year.ToString().Substring(2) +hour.ToString() + min.ToString(); //add in 2D at the end and write the line line2 += "2D"; writer.WriteLine(line2); //Finally we add the 3rd line which is comments writer.WriteLine(mol.Comments); }
private void CheckFormulaKeys(object sender, System.Windows.Forms.KeyPressEventArgs e) { if (e.KeyChar == (char)13) //if enter has been pressed we try and build a molecule from the formula { molecule = new Molecule(this); molecule.Formula = formulaTextBox.Text; molecule.OnlyHasFormula = true; molWeightLabel.Text = molecule.MolecularWeight.ToString(); } }
public object Clone() { //First we make a copy of the atoms Dictionary<int, Node> atomCopy = new Dictionary<int, Node>(); foreach (int id in atoms.Keys) { atomCopy.Add(id, (Node) atoms[id].Clone()); } //Then a copy of the bonds List<Bond> bondCopy = new List<Bond>(); foreach (Bond bond in bonds) { bondCopy.Add((Bond)bond.Clone()); } Molecule copy = new Molecule(atomCopy, this.name, this.numberOfAtoms, this.numberOfBonds, this.createdBy, this.buildSoftware, this.comments, bondCopy, this.form); return copy; }
private static void WriteCountsLine(StreamWriter writer, Molecule mol) { string line = string.Empty; string atomCount = mol.Atoms.Count.ToString(); atomCount = atomCount.PadLeft(3, ' '); line += atomCount; //Next are the bonds string bondCount = mol.Bonds.Count.ToString(); bondCount = bondCount.PadLeft(3, ' '); line += bondCount; //next we skip to the chiral spot line += " 0 "; if (mol.IsChiral) line += "1"; else line += "0"; //Then we write the rest of the line 0 0 0 0 0 0999 V2000 line += " 0 0 0 0 0 0999 V2000"; writer.WriteLine(line); }
private void AddCompoundForm_Load(object sender, EventArgs e) { //Build the type selection drop down box typeSelection.Items.Add("Reactant"); typeSelection.Items.Add("Reagent"); typeSelection.Items.Add("Product"); typeSelection.SelectedIndex = 0; //Build the state selection drop down stateSelection.Items.Add("Solid"); stateSelection.Items.Add("Liquid"); stateSelection.Items.Add("Gas"); stateSelection.Items.Add("Solution"); stateSelection.SelectedIndex = 0; //The following unit selection boxes have to follow the UNIT_POWERS Enum, that is none = 0, u = 1, m = 2, k = 3 //Build the mols unit selection drop down molUnitSelection.Items.Add("mol"); molUnitSelection.Items.Add("umol"); molUnitSelection.Items.Add("mmol"); molUnitSelection.SelectedIndex = 0; //Build the mass unit selection drop down massUnitSelection.Items.Add("g"); massUnitSelection.Items.Add("ug"); massUnitSelection.Items.Add("mg"); massUnitSelection.Items.Add("kg"); massUnitSelection.SelectedIndex = 0; //Build the volume unit selection drop down volumeUnitSelection.Items.Add("l"); volumeUnitSelection.Items.Add("ul"); volumeUnitSelection.Items.Add("ml"); volumeUnitSelection.SelectedIndex = 2; molecule = new Molecule(); //setup event handler for the formula textbox this.formulaTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(CheckFormulaKeys); this.molsTextBox.KeyPress += new KeyPressEventHandler(molsTextBox_KeyPress); //Next we need to create the molViewer molViewer.Paint +=new PaintEventHandler(molViewer.paint); //If the synthesis already has a limiting reactant we remove the islimitingcheckbox if (currentSynthesis.LimitingReactant != null) { isLimitingCheckBox.Hide(); } }
public Compound(Molecule mol, string fileName, string directory, int compoundType, string formula, int compoundState, bool isTarget, double weight, double density, Unit mols, Unit mass, Unit volume) { molFileName = fileName; this.directory = directory; this.type = compoundType; this.molecule = mol; this.state = compoundState; this.isTarget = isTarget; this.density = density; this.mols = mols; this.mass = mass; this.volume = volume; DisplayRefNameWhenDrawn = false; }
public CompoundRegion(Compound comp, Molecule visualComp, RectangleF rect) { this.compound = comp; this.rect = rect; this.visualMol = visualComp; }
private BoundingBox GetBoundingBox(Molecule molecule, RectangleF region) { //First we find the min/max in x and y for all the points double minX = 0; double maxX = 0; double minY = 0; double maxY = 0; foreach (Node atom in molecule.Atoms.Values) { if (minX == 0) minX = atom.Position.X; if (maxX == 0) maxX = atom.Position.X; if (minY == 0) minY = atom.Position.Y; if (maxY == 0) maxY = atom.Position.Y; double currentX = atom.Position.X; double currentY = atom.Position.Y; if (currentX < minX) minX = currentX; if (currentX > maxX) maxX = currentX; if (currentY < minY) minY = currentY; if (currentY > maxY) maxY = currentY; } //So now we get the distance between min and max double distX = maxX - minX + region.X; double distY = maxY - minY + region.Y; //The center of this box is the dist/2 double midX = distX / 2 + region.X; double midY = distY / 2 + region.Y; return new BoundingBox((float)distX, (float)distY, new PointF((float)midX, (float)midY), new PointF((float)minX, (float)minY), 0); }
private void pasteMDL_Click(object sender, EventArgs e) { molecule = new Molecule(); GetMolFromClipboard(); //Now fill in the data fields, first is formula formulaTextBox.Text = molecule.Formula.ToString(); //Next is mol weight molWeightLabel.Text = molecule.MolecularWeight.ToString(); structurePasted = true; //and finally we set the molviewer's molecule molViewer.Mol = (Molecule) molecule.Clone(); molViewer.Invalidate(); //redraw the viewer }
private static void ParseBondBlock(StreamReader reader, ref Molecule mol) { //One bond per line in format // 111222tttsssxxxrrrccc first atom # second atom # bond type bond stereo //Generally there will be spaces otherwise this f***s up string line = string.Empty; for (int i = 0; i < mol.NumberOfBonds; i++) { string[] delim = { " " }; string[] parts = reader.ReadLine().Split(delim, StringSplitOptions.RemoveEmptyEntries); //The first two pars are atoms 1 and 2 int atom1Key, atom2Key; bool result = int.TryParse(parts[0], out atom1Key); if (!result) Console.WriteLine("Could not get the first atom number"); result = int.TryParse(parts[1], out atom2Key); if (!result) Console.WriteLine("Could not get the second atom number"); int bondOrder; result = int.TryParse(parts[2], out bondOrder); if (!result) Console.WriteLine("Could not get the bond order for "+atom1Key+"'s connection to"+atom2Key); //Now we build the bond try { Bond bondToAdd = new Bond(mol.Atoms[atom1Key], mol.Atoms[atom2Key], bondOrder); mol.Bonds.Add(bondToAdd); } catch (ArgumentOutOfRangeException) { Console.WriteLine("The keys found were out of range 1:" + atom1Key + " 2:" + atom2Key + " atom count" + mol.Atoms.Count); } } }
private static void ParsePropertiesBlock(StreamReader reader, ref Molecule mol) { //properties block is mmm lines (999) and ends with M END //We check real fast to see if there is even any props string line = reader.ReadLine(); if (line == "M END") { Console.WriteLine("Mol file has been completely parsed \n"); return; //we're done jump out } }
private static void ParseHeaderBlock(StreamReader reader, ref Molecule mol) { //Line 1 : molecule name, can be blank, no longer than 80 letters mol.Name = reader.ReadLine(); if (mol.Name.Length > 80) Console.WriteLine("Name in mol file was too long"); /*Line 2: IIPPPPPPPPMMDDYYHHmmddSSssssssssssEEEEEEEEEEEERRRRRR *User's first and last initials (l), program name (P), *date/time (M/D/Y,H:m), dimensional codes (d), scaling factors (S, s), * energy (E) if modeling program input, * internal registry number (R) if input through MDL form. * can be blank */ string line2 = reader.ReadLine(); if (!string.IsNullOrEmpty(line2)) { mol.CreatedBy = line2.Substring(0, 2); mol.BuildSoftware = line2.Substring(2, 8); //To get the date time we need to shove in some characters so it parses correctly string originalDT = line2.Substring(10, 10); int month; int.TryParse(originalDT.Substring(0, 2), out month); int day; int.TryParse(originalDT.Substring(2, 2), out day); int year; int.TryParse(originalDT.Substring(4, 2), out year); year += 2000; //add 2000 to the year so we get the correct year, at least for the next 90 years int hour; int.TryParse(originalDT.Substring(6, 2), out hour); int min; int.TryParse(originalDT.Substring(8, 2), out min); DateTime dt = new DateTime(year, month, day, hour, min, 0); //To be added if needed Console.WriteLine("MOL creation time was changed to " + dt.ToString()); mol.CreationTime = dt; } //Line 3 is for comments mol.Comments = reader.ReadLine(); }
private static void ParseCountsLine(StreamReader reader, ref Molecule mol) { //it goes //aaabbblllfffcccsssxxxrrrpppiiimmm string countsLine = reader.ReadLine(); //We split by spaces string[] delim = {" "}; string[] parts = countsLine.Split(delim, StringSplitOptions.RemoveEmptyEntries); //Only three of the parts are useful, number of atoms, number of bonds //and whether or not the molecule is chiral, so spots 0, 1, 4 int nAtoms; int nBonds; int isChiral; bool result = int.TryParse(parts[0], out nAtoms); if (!result) { Console.WriteLine("Could not get the number of atoms"); } else mol.NumberOfAtoms = nAtoms; result = int.TryParse(parts[1], out nBonds); if (!result) { Console.WriteLine("Could not get the númber of bonds"); } else mol.NumberOfBonds = nBonds; result = int.TryParse(parts[4], out isChiral); if (!result) { Console.WriteLine("Could not get whether molecule is chiral."); } else { if (isChiral == 0) mol.IsChiral = false; else mol.IsChiral = true; } }
public Compound(Molecule mol, string refname, int compoundType, int compoundState, bool isLimiting, bool isTarget, double density, Unit mols, Unit mass, Unit volume, Solution solution) { this.type = compoundType; this.refName = refname; this.molecule = mol; this.state = compoundState; this.isLimiting = isLimiting; this.isTarget = isTarget; this.density = density; this.mols = mols; this.mass = mass; this.volume = volume; this.solution = solution; DisplayRefNameWhenDrawn = false; }
public Compound(string name, string refid, string localid, int fileid, int compoundType, int compoundState, bool isLimiting, bool isTarget, string formula, double density, Unit mols, Unit mass, Unit volume, Solution solution) { this.type = compoundType; this.molecule = new Molecule(); this.molecule.Name = name; this.refName = refid; this.localid = localid; this.fileid = fileid; this.state = compoundState; this.isLimiting = isLimiting; this.isTarget = isTarget; this.molecule.Formula = formula; this.density = density; this.mols = mols; this.mass = mass; this.volume = volume; this.solution = solution; DisplayRefNameWhenDrawn = false; }
private void DrawMolecule(Molecule mol, Graphics g) { //First we draw bonds foreach (Bond bond in mol.Bonds) { PointF p1 = new PointF((float)bond.Node1.Position.X, (float)bond.Node1.Position.Y); PointF p2 = new PointF((float)bond.Node2.Position.X, (float)bond.Node2.Position.Y); DrawBonds(g, p1, p2, bond.BondOrder, bond.WhichSide); } //Then we draw symbols foreach (Node atom in mol.Atoms.Values) { if (atom.Symbol != "C") { //First we draw a white circle with radius 10 at the atom location g.FillEllipse(Brushes.White, (float)atom.Position.X - 10, (float)atom.Position.Y - 10, 20, 20); //Then we draw the symbol string symbol = atom.Symbol; if (symbol == "S" || symbol == "O" || symbol == "N") { if (atom.ImplicitHydrogens == 0) { g.DrawString(symbol, font, Brushes.Black, (float)atom.Position.X - 9, (float)atom.Position.Y - 12); continue; } else if (atom.ImplicitHydrogens == 1) { symbol += "H"; g.DrawString(symbol, font, Brushes.Black, (float)atom.Position.X - 9, (float)atom.Position.Y - 12); continue; } else { //If there are more than one hydrogen we have to make a sub script Font normalFont = font; Font subscriptFont = new Font("Times New Roman", 10); symbol += "H"; g.DrawString(symbol, normalFont, Brushes.Black, (float)atom.Position.X - 9, (float)atom.Position.Y - 12); g.DrawString(atom.ImplicitHydrogens.ToString(), subscriptFont, Brushes.Black, (float)atom.Position.X + 20, (float)(atom.Position.Y + 5)); continue; } } g.DrawString(symbol, font, Brushes.Black, (float)atom.Position.X - 9, (float)atom.Position.Y - 12); } } }
public Compound(Molecule mol) { this.molecule = mol; this.mols = new Unit(0, "mol", (int)UNIT_POWERS.none); this.mass = new Unit(0, "g", (int)UNIT_POWERS.none); this.Volume = new Unit(0, "l", (int)UNIT_POWERS.m); DisplayRefNameWhenDrawn = false; }
private void NormalizeCoords(Molecule mol, COMPOUND_TYPES type, int id) { if (mol == null) return; //First we get the region we are working in RectangleF region; if (type == COMPOUND_TYPES.Reactant) region = reactantRegions[id]; else if (type == COMPOUND_TYPES.Reagent) region = reagentRegions[0]; //we only ever have one reagent region else region = productRegions[id]; //we get the bounds of the raw copy for initial sizing for the given region mol.Bounds = GetBoundingBox(mol, region); PointF center = new PointF(region.X + region.Width / 2, region.Y + region.Height / 2); //The scale values for x and y are then calculated //We want to keep the same ratio so we get the ratio, find the max sx can be and then calculte sy from that float ratio = mol.Bounds.Width/mol.Bounds.Height; double sx = 40; //region.Width / mol.Bounds.Width-30; double sy = 30; //ratio / sx; foreach (Node atom in mol.Atoms.Values) { double ox = atom.Position.X; double oy = atom.Position.Y; double x = (ox * sx + center.X); double y = (oy * sy + center.Y); atom.Position = new Vector3(x, y, 0); //Finally we go through the bonds and update their nodes, due to some error in copying foreach (Bond bond in mol.Bonds) { if (bond.Node1.ID == atom.ID) bond.Node1 = atom; else if (bond.Node2.ID == atom.ID) bond.Node2 = atom; } //and again go through one more time to calculate the paths foreach (Bond bond in mol.Bonds) { bond.CalculateBoundPath(); } } //We also need to get the new size of the bounding box and get the bounds for each bond mol.Bounds = GetBoundingBox(mol, region); }
private static void ReadMolData(XmlDocument doc, List<Compound> compounds) { //We read in the mol data, with the compound file id and then fill the molecule out with information //First we find the correct xml node XmlNodeList molDataNodes = doc.GetElementsByTagName("moldata"); //now we run through the nodes foreach (XmlNode node in molDataNodes) { foreach (Compound c in compounds) { if (c.FileID == int.Parse(node.Attributes["fileid"].Value)) { Molecule m = new Molecule(); if (node.InnerText == string.Empty) { //sometimes we have no mol data, just a formula m.Formula = node.Attributes["formula"].Value; m.OnlyHasFormula = true; } else { MolFileReader.ReadMolData(node.InnerText, ref m); } Console.WriteLine(m.ToString()); c.MoleculeData = m; } } } }