private IChemFile ReadChemFile(IChemFile file) { IChemSequence seq = file.Builder.NewChemSequence(); IChemModel model = file.Builder.NewChemModel(); ICrystal crystal = null; int lineNumber = 0; Vector3 a, b, c; try { string line = input.ReadLine(); while (line != null) { Debug.WriteLine($"{lineNumber++}: {line}"); if (line.StartsWith("frame:", StringComparison.Ordinal)) { Debug.WriteLine("found new frame"); model = file.Builder.NewChemModel(); crystal = file.Builder.NewCrystal(); // assume the file format is correct Debug.WriteLine("reading spacegroup"); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); crystal.SpaceGroup = line; Debug.WriteLine("reading unit cell axes"); Vector3 axis = new Vector3(); Debug.WriteLine("parsing A: "); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); axis.X = FortranFormat.Atof(line); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); axis.Y = FortranFormat.Atof(line); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); axis.Z = FortranFormat.Atof(line); crystal.A = axis; axis = new Vector3(); Debug.WriteLine("parsing B: "); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); axis.X = FortranFormat.Atof(line); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); axis.Y = FortranFormat.Atof(line); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); axis.Z = FortranFormat.Atof(line); crystal.B = axis; axis = new Vector3(); Debug.WriteLine("parsing C: "); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); axis.X = FortranFormat.Atof(line); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); axis.Y = FortranFormat.Atof(line); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); axis.Z = FortranFormat.Atof(line); crystal.C = axis; Debug.WriteLine($"Crystal: {crystal}"); a = crystal.A; b = crystal.B; c = crystal.C; Debug.WriteLine("Reading number of atoms"); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); int atomsToRead = int.Parse(line, NumberFormatInfo.InvariantInfo); Debug.WriteLine("Reading no molecules in assym unit cell"); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); int Z = int.Parse(line, NumberFormatInfo.InvariantInfo); crystal.Z = Z; string symbol; double charge; Vector3 cart; for (int i = 1; i <= atomsToRead; i++) { cart = new Vector3(); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); symbol = line.Substring(0, line.IndexOf(':')); charge = double.Parse(line.Substring(line.IndexOf(':') + 1), NumberFormatInfo.InvariantInfo); line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); cart.X = double.Parse(line, NumberFormatInfo.InvariantInfo); // x line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); cart.Y = double.Parse(line, NumberFormatInfo.InvariantInfo); // y line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); cart.Z = double.Parse(line, NumberFormatInfo.InvariantInfo); // z IAtom atom = file.Builder.NewAtom(symbol); atom.Charge = charge; // convert Cartesian coords to fractional Vector3 frac = CrystalGeometryTools.CartesianToFractional(a, b, c, cart); atom.FractionalPoint3D = frac; crystal.Atoms.Add(atom); Debug.WriteLine($"Added atom: {atom}"); } model.Crystal = crystal; seq.Add(model); } else { Debug.WriteLine("Format seems broken. Skipping these lines:"); while (line != null && !line.StartsWith("frame:", StringComparison.Ordinal)) { line = input.ReadLine(); Debug.WriteLine($"{lineNumber++}: {line}"); } Debug.WriteLine("Ok, resynched: found new frame"); } } file.Add(seq); } catch (Exception exception) { if (!(exception is IOException || exception is ArgumentException)) { throw; } string message = "Error while parsing CrystClust file: " + exception.Message; Trace.TraceError(message); Debug.WriteLine(exception); throw new CDKException(message, exception); } return(file); }
private string ProcessAtomLoopBlock(string firstLine) { int atomLabel = -1; // -1 means not found in this block int atomSymbol = -1; int atomFractX = -1; int atomFractY = -1; int atomFractZ = -1; int atomRealX = -1; int atomRealY = -1; int atomRealZ = -1; string line = firstLine.Trim(); int headerCount = 0; bool hasParsableInformation = false; while (line != null && line[0] == '_') { headerCount++; if (line.Equals("_atom_site_label", StringComparison.Ordinal) || line.Equals("_atom_site_label_atom_id", StringComparison.Ordinal)) { atomLabel = headerCount; hasParsableInformation = true; Trace.TraceInformation($"label found in col: {atomLabel}"); } else if (line.StartsWith("_atom_site_fract_x", StringComparison.Ordinal)) { atomFractX = headerCount; hasParsableInformation = true; Trace.TraceInformation("frac x found in col: " + atomFractX); } else if (line.StartsWith("_atom_site_fract_y", StringComparison.Ordinal)) { atomFractY = headerCount; hasParsableInformation = true; Trace.TraceInformation("frac y found in col: " + atomFractY); } else if (line.StartsWith("_atom_site_fract_z", StringComparison.Ordinal)) { atomFractZ = headerCount; hasParsableInformation = true; Trace.TraceInformation("frac z found in col: " + atomFractZ); } else if (string.Equals(line, "_atom_site.Cartn_x", StringComparison.Ordinal)) { atomRealX = headerCount; hasParsableInformation = true; Trace.TraceInformation("cart x found in col: " + atomRealX); } else if (string.Equals(line, "_atom_site.Cartn_y", StringComparison.Ordinal)) { atomRealY = headerCount; hasParsableInformation = true; Trace.TraceInformation("cart y found in col: " + atomRealY); } else if (string.Equals(line, "_atom_site.Cartn_z", StringComparison.Ordinal)) { atomRealZ = headerCount; hasParsableInformation = true; Trace.TraceInformation("cart z found in col: " + atomRealZ); } else if (string.Equals(line, "_atom_site.type_symbol", StringComparison.Ordinal)) { atomSymbol = headerCount; hasParsableInformation = true; Trace.TraceInformation("type_symbol found in col: " + atomSymbol); } else { Trace.TraceWarning("Ignoring atom loop block field: " + line); } line = input.ReadLine().Trim(); } if (!hasParsableInformation) { Trace.TraceInformation("No parsable info found"); return(SkipLoopBody(line)); } else { // now that headers are parsed, read the data while (line != null && line.Length > 0 && line[0] != '#' && line[0] != '_' && !line.StartsWith("loop_", StringComparison.Ordinal) && !line.StartsWith("data_", StringComparison.Ordinal)) { Debug.WriteLine("new row"); var tokenizer = Strings.Tokenize(line); if (tokenizer.Count < headerCount) { Trace.TraceWarning("Column count mismatch; assuming continued on next line"); Debug.WriteLine($"Found #expected, #found:{headerCount}, {tokenizer.Count}"); tokenizer = Strings.Tokenize(line + input.ReadLine()); } int colIndex = 0; // process one row IAtom atom = crystal.Builder.NewAtom("C"); Vector3 frac = new Vector3(); Vector3 real = new Vector3(); bool hasFractional = false; bool hasCartesian = false; foreach (var field in tokenizer) { colIndex++; Debug.WriteLine("Parsing col,token: " + colIndex + "=" + field); if (colIndex == atomLabel) { if (atomSymbol == -1) { // no atom symbol found, use label string element = ExtractFirstLetters(field); atom.Symbol = element; } atom.Id = field; } else if (colIndex == atomFractX) { hasFractional = true; frac.X = ParseIntoDouble(field); } else if (colIndex == atomFractY) { hasFractional = true; frac.Y = ParseIntoDouble(field); } else if (colIndex == atomFractZ) { hasFractional = true; frac.Z = ParseIntoDouble(field); } else if (colIndex == atomSymbol) { atom.Symbol = field; } else if (colIndex == atomRealX) { hasCartesian = true; Debug.WriteLine("Adding x3: " + ParseIntoDouble(field)); real.X = ParseIntoDouble(field); } else if (colIndex == atomRealY) { hasCartesian = true; Debug.WriteLine("Adding y3: " + ParseIntoDouble(field)); real.Y = ParseIntoDouble(field); } else if (colIndex == atomRealZ) { hasCartesian = true; Debug.WriteLine("Adding x3: " + ParseIntoDouble(field)); real.Z = ParseIntoDouble(field); } } if (hasCartesian) { Vector3 a = crystal.A; Vector3 b = crystal.B; Vector3 c = crystal.C; frac = CrystalGeometryTools.CartesianToFractional(a, b, c, real); atom.FractionalPoint3D = frac; } if (hasFractional) { atom.FractionalPoint3D = frac; } Debug.WriteLine($"Adding atom: {atom}"); crystal.Atoms.Add(atom); // look up next row line = input.ReadLine(); if (line != null) { line = line.Trim(); } } } return(line); }
// Private procedures private void WriteCrystal(ICrystal crystal) { var title = crystal.Title; if (title != null && title.Trim().Length > 0) { Writeln($"TITL {title.Trim()}"); } else { Writeln("TITL Produced with CDK (http://cdk.sf.net/)"); } Vector3 a = crystal.A; Vector3 b = crystal.B; Vector3 c = crystal.C; double alength = a.Length(); double blength = b.Length(); double clength = c.Length(); double alpha = Vectors.RadianToDegree(Vectors.Angle(b, c)); double beta = Vectors.RadianToDegree(Vectors.Angle(a, c)); double gamma = Vectors.RadianToDegree(Vectors.Angle(a, b)); Write("CELL " + 1.54184.ToString("F5", NumberFormatInfo.InvariantInfo) + " "); Write(alength.ToString("F5", NumberFormatInfo.InvariantInfo) + " "); Write(blength.ToString("F5", NumberFormatInfo.InvariantInfo) + " "); Write(clength.ToString("F5", NumberFormatInfo.InvariantInfo) + " "); Write(alpha.ToString("F4", NumberFormatInfo.InvariantInfo) + " "); Write(beta.ToString("F4", NumberFormatInfo.InvariantInfo) + " "); Write(gamma.ToString("F4", NumberFormatInfo.InvariantInfo) + " "); Writeln("ZERR " + ((double)crystal.Z).ToString("F5", NumberFormatInfo.InvariantInfo) + " 0.01000 0.01000 0.01000 0.0100 0.0100 0.0100"); string spaceGroup = crystal.SpaceGroup; if (string.Equals("P1", spaceGroup, StringComparison.Ordinal)) { Writeln("LATT -1"); } else if (string.Equals("P 2_1 2_1 2_1", spaceGroup, StringComparison.Ordinal)) { Writeln("LATT -1"); Writeln("SYMM 1/2+X , 1/2-Y , -Z"); Writeln("SYMM -X , 1/2+Y , 1/2-Z"); Writeln("SYMM 1/2-X , -Y , 1/2+Z"); } string elemNames = ""; string elemCounts = ""; IMolecularFormula formula = MolecularFormulaManipulator.GetMolecularFormula(crystal); var asortedElements = MolecularFormulaManipulator.Elements(formula).ToReadOnlyList(); foreach (var element in asortedElements) { string symbol = element.Symbol; elemNames += symbol + " ".Substring(symbol.Length); string countS = MolecularFormulaManipulator.GetElementCount(formula, element).ToString(NumberFormatInfo.InvariantInfo); elemCounts += countS + " ".Substring(countS.Length); } Writeln("SFAC " + elemNames); Writeln("UNIT " + elemCounts); /* write atoms */ for (int i = 0; i < crystal.Atoms.Count; i++) { IAtom atom = crystal.Atoms[i]; Vector3 cartCoord = atom.Point3D.Value; Vector3 fracCoord = CrystalGeometryTools.CartesianToFractional(a, b, c, cartCoord); string symbol = atom.Symbol; string output = symbol + (i + 1); Write(output); for (int j = 1; j < 5 - output.Length; j++) { Write(" "); } Write(" "); string elemID = null; for (int elemidx = 0; elemidx < asortedElements.Count; elemidx++) { var elem = asortedElements[elemidx]; if (elem.Symbol.Equals(symbol, StringComparison.Ordinal)) { elemID = (elemidx + 1).ToString(NumberFormatInfo.InvariantInfo); break; } } Write(elemID); Write(" ".Substring(elemID.Length)); Write(fracCoord.X.ToString("F5", NumberFormatInfo.InvariantInfo) + " "); Write(fracCoord.Y.ToString("F5", NumberFormatInfo.InvariantInfo) + " "); Writeln(fracCoord.Y.ToString("F5", NumberFormatInfo.InvariantInfo) + " 11.00000 0.05000"); } Writeln("END"); }