/// <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);
        }
    }
Exemple #2
0
    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);
    }