public override void TestAdd_IAtomContainer() { ICrystal crystal = (ICrystal)NewChemObject(); IAtomContainer acetone = crystal.Builder.NewAtomContainer(); IAtom c1 = crystal.Builder.NewAtom("C"); IAtom c2 = crystal.Builder.NewAtom("C"); IAtom o = crystal.Builder.NewAtom("O"); IAtom c3 = crystal.Builder.NewAtom("C"); acetone.Atoms.Add(c1); acetone.Atoms.Add(c2); acetone.Atoms.Add(c3); acetone.Atoms.Add(o); IBond b1 = crystal.Builder.NewBond(c1, c2, BondOrder.Single); IBond b2 = crystal.Builder.NewBond(c1, o, BondOrder.Double); IBond b3 = crystal.Builder.NewBond(c1, c3, BondOrder.Single); acetone.Bonds.Add(b1); acetone.Bonds.Add(b2); acetone.Bonds.Add(b3); crystal.Add(acetone); Assert.AreEqual(4, crystal.Atoms.Count); Assert.AreEqual(3, crystal.Bonds.Count); }
public virtual void TestStateChanged_EventPropagation_Crystal() { ChemObjectListenerImpl listener = new ChemObjectListenerImpl(); IChemModel chemObject = (IChemModel)NewChemObject(); chemObject.Listeners.Add(listener); ICrystal crystal = chemObject.Builder.NewCrystal(); chemObject.Crystal = crystal; Assert.IsTrue(listener.Changed); // reset the listener listener.Reset(); Assert.IsFalse(listener.Changed); // changing the set should trigger a change event in the IChemModel crystal.Add(chemObject.Builder.NewAtomContainer()); Assert.IsTrue(listener.Changed); }
public virtual void TestStateChanged_ButNotAfterRemoval_Crystal() { ChemObjectListenerImpl listener = new ChemObjectListenerImpl(); IChemModel chemObject = (IChemModel)NewChemObject(); chemObject.Listeners.Add(listener); ICrystal crystal = chemObject.Builder.NewCrystal(); chemObject.Crystal = crystal; Assert.IsTrue(listener.Changed); // remove the set from the IChemModel chemObject.Crystal = null; // reset the listener listener.Reset(); Assert.IsFalse(listener.Changed); // changing the set must *not* trigger a change event in the IChemModel crystal.Add(chemObject.Builder.NewAtomContainer()); Assert.IsFalse(listener.Changed); }
/// <summary> /// Private method that actually parses the input to read a ChemFile /// object. /// /// Each PMP frame is stored as a Crystal in a ChemModel. The PMP /// file is stored as a ChemSequence of ChemModels. /// </summary> /// <returns>A ChemFile containing the data parsed from input.</returns> private IChemFile ReadChemFile(IChemFile chemFile) { IChemSequence chemSequence = chemFile.Builder.NewChemSequence(); IChemModel chemModel = chemFile.Builder.NewChemModel(); ICrystal crystal = chemFile.Builder.NewCrystal(); try { string line = ReadLine(); while (line != null) { if (line.StartsWith("%%Header Start", StringComparison.Ordinal)) { // parse Header section while (line != null && !(line.StartsWith("%%Header End", StringComparison.Ordinal))) { if (line.StartsWith("%%Version Number", StringComparison.Ordinal)) { string version = ReadLine().Trim(); if (!string.Equals(version, "3.00", StringComparison.Ordinal)) { Trace.TraceError("The PMPReader only supports PMP files with version 3.00"); return(null); } } line = ReadLine(); } } else if (line.StartsWith("%%Model Start", StringComparison.Ordinal)) { // parse Model section modelStructure = chemFile.Builder.NewAtomContainer(); while (line != null && !(line.StartsWith("%%Model End", StringComparison.Ordinal))) { var objHeaderMatcher = objHeader.Match(line); if (objHeaderMatcher.Success) { string obj = objHeaderMatcher.Groups[2].Value; ConstructObject(chemFile.Builder, obj); int id = int.Parse(objHeaderMatcher.Groups[1].Value, NumberFormatInfo.InvariantInfo); // Debug.WriteLine(object + " id: " + id); line = ReadLine(); while (line != null && !(string.Equals(line.Trim(), ")", StringComparison.Ordinal))) { // parse object command (or new object header) var objCommandMatcher = objCommand.Match(line); objHeaderMatcher = objHeader.Match(line); if (objHeaderMatcher.Success) { // ok, forget about nesting and hope for the best obj = objHeaderMatcher.Groups[2].Value; id = int.Parse(objHeaderMatcher.Groups[1].Value, NumberFormatInfo.InvariantInfo); ConstructObject(chemFile.Builder, obj); } else if (objCommandMatcher.Success) { string format = objCommandMatcher.Groups[1].Value; string command = objCommandMatcher.Groups[2].Value; string field = objCommandMatcher.Groups[3].Value; ProcessModelCommand(obj, command, format, field); } else { Trace.TraceWarning("Skipping line: " + line); } line = ReadLine(); } if (chemObject is IAtom) { atomids[id] = modelStructure.Atoms.Count; atomZOrders[int.Parse(chemObject.GetProperty <string>(PMP_ZORDER), NumberFormatInfo.InvariantInfo)] = id; atomGivenIds[int.Parse(chemObject.GetProperty <string>(PMP_ID), NumberFormatInfo.InvariantInfo)] = id; modelStructure.Atoms.Add((IAtom)chemObject); } else if (chemObject is IBond) { // ignored: bonds may be defined before their // atoms so their handling is deferred until the // end of the model } else { Trace.TraceError("chemObject is not initialized or of bad class type"); } } line = ReadLine(); } if (line.StartsWith("%%Model End", StringComparison.Ordinal)) { // during the Model Start, all bonds are cached as PMP files might // define bonds *before* the involved atoms :( // the next lines dump the cache into the atom container int bondsFound = bondids.Count; Debug.WriteLine($"Found #bonds: {bondsFound}"); Debug.WriteLine($"#atom ones: {bondAtomOnes.Count}"); Debug.WriteLine($"#atom twos: {bondAtomTwos.Count}"); Debug.WriteLine($"#orders: {bondOrders.Count}"); foreach (var index in bondids.Keys) { if (!bondOrders.TryGetValue(index, out double order)) { order = 1; } Debug.WriteLine($"index: {index}"); Debug.WriteLine($"ones: {bondAtomOnes[index]}"); IAtom atom1 = modelStructure.Atoms[atomids[bondAtomOnes[index]]]; IAtom atom2 = modelStructure.Atoms[atomids[bondAtomTwos[index]]]; IBond bond = modelStructure.Builder.NewBond(atom1, atom2); if (order == 1.0) { bond.Order = BondOrder.Single; } else if (order == 2.0) { bond.Order = BondOrder.Double; } else if (order == 3.0) { bond.Order = BondOrder.Triple; } else if (order == 4.0) { bond.Order = BondOrder.Quadruple; } modelStructure.Bonds.Add(bond); } } } else if (line.StartsWith("%%Traj Start", StringComparison.Ordinal)) { chemSequence = chemFile.Builder.NewChemSequence(); double energyFragment = 0.0; double energyTotal = 0.0; int Z = 1; while (line != null && !(line.StartsWith("%%Traj End", StringComparison.Ordinal))) { if (line.StartsWith("%%Start Frame", StringComparison.Ordinal)) { chemModel = chemFile.Builder.NewChemModel(); crystal = chemFile.Builder.NewCrystal(); while (line != null && !(line.StartsWith("%%End Frame", StringComparison.Ordinal))) { // process frame data if (line.StartsWith("%%Atom Coords", StringComparison.Ordinal)) { // calculate Z: as it is not explicitely given, try to derive it from the // energy per fragment and the total energy if (energyFragment != 0.0 && energyTotal != 0.0) { Z = (int)Math.Round(energyTotal / energyFragment); Debug.WriteLine($"Z derived from energies: {Z}"); } // add atomC as atoms to crystal int expatoms = modelStructure.Atoms.Count; for (int molCount = 1; molCount <= Z; molCount++) { IAtomContainer clone = modelStructure.Builder.NewAtomContainer(); for (int i = 0; i < expatoms; i++) { line = ReadLine(); IAtom a = clone.Builder.NewAtom(); var st = Strings.Tokenize(line, ' '); a.Point3D = new Vector3(double.Parse(st[0], NumberFormatInfo.InvariantInfo), double.Parse(st[1], NumberFormatInfo.InvariantInfo), double.Parse(st[2], NumberFormatInfo.InvariantInfo)); a.CovalentRadius = 0.6; IAtom modelAtom = modelStructure.Atoms[atomids[atomGivenIds[i + 1]]]; a.Symbol = modelAtom.Symbol; clone.Atoms.Add(a); } rebonder.Rebond(clone); crystal.Add(clone); } } else if (line.StartsWith("%%E/Frag", StringComparison.Ordinal)) { line = ReadLine().Trim(); energyFragment = double.Parse(line, NumberFormatInfo.InvariantInfo); } else if (line.StartsWith("%%Tot E", StringComparison.Ordinal)) { line = ReadLine().Trim(); energyTotal = double.Parse(line, NumberFormatInfo.InvariantInfo); } else if (line.StartsWith("%%Lat Vects", StringComparison.Ordinal)) { line = ReadLine(); IList <string> st; st = Strings.Tokenize(line, ' '); crystal.A = new Vector3(double.Parse(st[0], NumberFormatInfo.InvariantInfo), double.Parse(st[1], NumberFormatInfo.InvariantInfo), double.Parse(st[2], NumberFormatInfo.InvariantInfo)); line = ReadLine(); st = Strings.Tokenize(line, ' '); crystal.B = new Vector3(double.Parse(st[0], NumberFormatInfo.InvariantInfo), double.Parse(st[1], NumberFormatInfo.InvariantInfo), double.Parse(st[2], NumberFormatInfo.InvariantInfo)); line = ReadLine(); st = Strings.Tokenize(line, ' '); crystal.C = new Vector3(double.Parse(st[0], NumberFormatInfo.InvariantInfo), double.Parse(st[1], NumberFormatInfo.InvariantInfo), double.Parse(st[2], NumberFormatInfo.InvariantInfo)); } else if (line.StartsWith("%%Space Group", StringComparison.Ordinal)) { line = ReadLine().Trim(); // standardize space group name. See Crystal.SetSpaceGroup() if (string.Equals("P 21 21 21 (1)", line, StringComparison.Ordinal)) { crystal.SpaceGroup = "P 2_1 2_1 2_1"; } else { crystal.SpaceGroup = "P1"; } } else { } line = ReadLine(); } chemModel.Crystal = crystal; chemSequence.Add(chemModel); } line = ReadLine(); } chemFile.Add(chemSequence); } else { // disregard line } // read next line line = ReadLine(); } } catch (IOException e) { Trace.TraceError($"An IOException happened: {e.Message}"); Debug.WriteLine(e); chemFile = null; } catch (CDKException e) { Trace.TraceError($"An CDKException happened: {e.Message}"); Debug.WriteLine(e); chemFile = null; } return(chemFile); }