/// <summary> /// Find all particles from the MELDB which has the same structure as provided /// </summary> /// <param name="atoms">atom elements list</param> /// <param name="exact">pass true if you want compare bond types also</param> /// <returns>first found particle; null if not found</returns> public static IEnumerator FindParticles(List <ParticleInfo> results, List <Element> atoms, List <BondInfo> bonds, bool exact = true, ParticleInfo.ParticleFlags flags = ParticleInfo.ParticleFlags.None) { var aHash = ParticleInfo.GetAtomsHash(atoms); results.Clear(); int startIndx, endIndx; InnerSearch(aHash, out startIndx, out endIndx); if (startIndx < 0) { yield break; } yield return(null); var particles = Instance.particles; var sorting = Instance.__sortedAtomsHashes; uint hash = 0; for (int i = startIndx; i <= endIndx; i++) { var p = particles[sorting[i]]; if ((p.flags & flags) != flags) { continue; } if (hash == 0) // we do want to avoid this operation as long as possible, so it should be here { hash = ParticleComparer.GetStructureHash(atoms, bonds, exact); yield return(null); } var pHash = exact ? p.structureHashExact : p.structureHash; if (pHash != hash) { continue; } if (ParticleComparer.AreEqual(atoms, bonds, p, exact, (ParticleComparer.AtomsReordering)null, false)) { results.Add(p); } yield return(null); } }
public static bool Test(ParticleInfo p) { var c = p.CreateCopy(); var reord = new List <int>(p.atoms.Count); for (int test = 0; test < TESTS; test++) { c.Shuffle(); var atoms = c.atoms.Select(x => x.element).ToList(); var bonds = c.bonds; //Debug.LogWarning("1. SHUFFLED:\n" + string.Join(", ", atoms.Select(x => x.ToString()).ToArray()) + "\n"); //Debug.LogWarning("2. ORIGINAL:\n" + string.Join(", ", p.atoms.Select(x => x.element.ToString()).ToArray()) + "\n"); //Debug.LogWarning(string.Join(", ", bonds.Select(x => x.atom1 + "-" + x.atom2).ToArray()) + "\n"); //Debug.LogWarning(string.Join(", ", p.bonds.Select(x => x.atom1 + "-" + x.atom2).ToArray()) + "\n"); foreach (var b in c.bonds) { b.bondType = BondInfo.BondType.SINGLE; } if (ParticleComparer.AreEqual(atoms, bonds, p, false, reord)) { //Debug.Log("YES\n"); //var rdr = new List<Element>(atoms.Count); //Debug.LogWarning(string.Join(", ", reord.Select(x => x.ToString()).ToArray()) + "\nREORDERING"); //for (int i = 0; i < p.atoms.Count; i++) //rdr.Add(p.atoms[reord[i]].element); //Debug.LogWarning("REORDERED:\n" + string.Join(", ", rdr.Select(x => x.ToString()).ToArray()) + "\n"); } else { Debug.LogError("NO!!!\n" + p.name); return(false); } } return(true); }
/// <summary> /// Take all new data from other particle. Id, charge and hashes are not taken /// </summary> /// <param name="source">particle to take data from</param> /// <param name="reorderings">temporary buffer</param> /// <returns>false if topology mismatch</returns> public bool TakeAbsentDataFrom(ParticleInfo source, List <int> reorderings, bool allowAutofix = false) { Init(); // data copied only if not present in destination // id stays the same // hashes are not updated, should be recalculated by the caller if (string.IsNullOrEmpty(name)) { name = source.name; } if (CID == 0) { CID = source.CID; } for (int i = 0; i < source.CASes.Count; i++) { if (!CASes.Contains(source.CASes[i])) { CASes.Add(source.CASes[i]); } } if ((flags & ParticleFlags.HasChemicalFormula) == 0) { chemicalFormula = source.chemicalFormula; flags |= (source.flags & ParticleFlags.HasChemicalFormula); } flags |= (source.flags & ParticleFlags.HasSkeletalFormula); flags |= (source.flags & ParticleFlags.ShowInExplorer); flags |= (source.flags & ParticleFlags.ShowInConstructor); flags |= (source.flags & ParticleFlags.ForceIncludeInBuild); bool success = true; var structureFlags = ParticleFlags.Has3D | ParticleFlags.Has2D; if ((flags & structureFlags) != structureFlags && // there is something missing (source.flags & structureFlags) > 0) // there is something to copy { var sAtoms = source.data.atoms; if ((flags & structureFlags) == 0) // everything is missing { // just copy the whole data data.atoms = DeepCopy(sAtoms); data.bonds = DeepCopy(source.bonds); // copy some flags from source var flagsToCopy = ParticleFlags.HasParticleCharge | ParticleFlags.HasAtomCharges | ParticleFlags.Has2D | ParticleFlags.Has3D | ParticleFlags.HasTopology | ParticleFlags.HasRadicalAtoms; flags &= ~flagsToCopy; flags |= (source.flags & flagsToCopy); } else { var atoms = data.atoms; success = ParticleComparer.AreEqual(this, source, true, reorderings); if (!success & allowAutofix) { success = ParticleComparer.AreEqual(this, source, false, reorderings); } if (success) { if ((flags & ParticleFlags.Has2D) == 0 & (source.flags & ParticleFlags.Has2D) > 0) { // we should take 2d from source, but keep our 3d for (int i = atoms.Count - 1; i >= 0; i--) { atoms[i].flatPosition = sAtoms[reorderings[i]].flatPosition; } flags |= ParticleFlags.Has2D | ParticleFlags.HasTopology; } else if ((flags & ParticleFlags.Has3D) == 0 & (source.flags & ParticleFlags.Has3D) > 0) { // we should take 3d from source, but keep our 2d for (int i = atoms.Count - 1; i >= 0; i--) { atoms[i].position = sAtoms[reorderings[i]].position; } flags |= ParticleFlags.Has3D | ParticleFlags.HasTopology; } // take charges if ((source.flags & ParticleFlags.HasAtomCharges) > 0) { flags |= (source.flags & (ParticleFlags.HasParticleCharge | ParticleFlags.HasAtomCharges)); for (int i = atoms.Count - 1; i >= 0; i--) { if (atoms[i].atomCharge == 0) { atoms[i].atomCharge = sAtoms[reorderings[i]].atomCharge; } } } // take radicals if ((source.flags & ParticleFlags.HasRadicalAtoms) > 0) { flags |= (source.flags & ParticleFlags.HasRadicalAtoms); for (int i = atoms.Count - 1; i >= 0; i--) { if (atoms[i].radical == 0) { atoms[i].radical = sAtoms[reorderings[i]].radical; } } } } } } if (string.IsNullOrEmpty(primaryName)) { primaryName = source.primaryName; } var sSynonyms = source.iupacs; for (int i = 0; i < sSynonyms.Count; i++) { var syn = sSynonyms[i]; if (syn.Equals(primaryName, StringComparison.Ordinal)) { continue; } if (iupacs.Contains(syn)) { continue; } iupacs.Add(syn); } return(success); }