Example #1
0
// Autocreate patterns
bool Model::createPatterns()
{
	// Determine the pattern (molecule) layout of the model
	Messenger::enter("Model::createPatterns");
	int n, atomid, nsel2, nmols, idi, idj, idoff, count;
	bool same;
	QString empirical;
	Clipboard patclip;
	Pattern* p;
	RefListItem<Bond,int>* rb;
	Atom* i, *selectSource;
	ClipAtom* clipi;
	RefListItem<Atom,int>* isel;
	
	// Check current pattern first...
	if (arePatternsValid())
	{
		Messenger::exit("Model::createPatterns");
		return true;
	}
	
	// Delete all old nodes first.
	Messenger::print("Autodetecting patterns for model '%s'..", qPrintable(name_));
	patterns_.clear();
	// If there are no atoms in the molecule, exit here.
	if (atoms_.nItems() == 0)
	{
		Messenger::print("No patterns defined for model '%s' - no atoms present.", qPrintable(name_));
		patternsPoint_ = log(Log::Structure);
		Messenger::exit("Model::createPatterns");
		return true;
	}
	
	// To autodetect, we start off at the first atom in the model, tree-select this atom and copy the selection to the clipboard. Use the clipboard to check subsequent selections, and if its the same just increase the nmols counter by one. If it's different, assume its the start of a new type of molecule and reset the counters.
	atomid = 0;
	nmols = 0;
	i = atoms_.first();
	while (atomid != atoms_.nItems())
	{
		selectNone(true);
		
		// Select molecule starting at atom 'i' and calculate fingerprint
		selectTree(i, true);
		selectSource = i;
		
		// We insist that the molecule consists of consecutively ordered atoms, otherwise we can't proceed, so count the number of selected
		// atoms in those that we now skip (if != nselected then we must force a 1*N pattern)
		nsel2 = 0;
		atomid += marked_.nItems();
		//selectionGetEmpirical(emp);
		for (n=0; n<marked_.nItems(); n++)
		{
			if (i->isSelected(true)) nsel2 ++;
			i = i->next;
		}
		if (nsel2 != marked_.nItems())
		{
			Messenger::error("Pattern creation failed because of bad atom ordering or the presence of additional bonds.");
			Messenger::error("Problem occurred in pattern %i whilst selecting from atom %i.", patterns_.nItems()+1, selectSource->id()+1);

			// Remove any patterns added so far
			patterns_.clear();
			nmols = 0;

			Messenger::exit("Model::createPatterns");
			return false;
		}
		// If this is the first pass (molecule), copy the selection. If not, compare it
		if (nmols == 0)
		{
			patclip.copyMarked(this);
			empirical = selectionEmpirical(true);
			nmols = 1;
		}
		else
		{
			// Compare clipboard contents with current selection
			same = true;
			// Check number of atoms first....
			if (marked_.nItems() != patclip.nAtoms()) same = false;
			else
			{
				// Atoms
				clipi = patclip.atoms();
				for (isel = marked_.first(); isel != NULL; isel = isel->next)
				{
					count++;
					
					// Element check
					if (clipi->atom().element() != isel->item->element())
					{
						same = false;
						break;
					}
					
					// Fixed position
					if (clipi->atom().isPositionFixed() != isel->item->isPositionFixed())
					{
						same = false;
						break;
					}

					// Fixed forcefield type check
					if (clipi->atom().hasFixedType() != isel->item->hasFixedType())
					{
						same = false;
						break;
					}
					else if (clipi->atom().hasFixedType())
					{
						// Both have fixed type - make sure types are the same
						if (clipi->atom().type() != isel->item->type())
						{
							same = false;
							break;
						}
					}
					clipi = clipi->next;
				}
				
				// Bonding between atoms (but only if atoms themselves check out)...
				if (same)
				{
					idoff = selection(true)->item->id();
					count = 0;
					for (isel = marked_.first(); isel != NULL; isel = isel->next)
					{
						// Convert IDs so they start at zero (i.e. subtract ID of current atom 'i')
						idi = isel->item->id() - idoff;
						for (rb = isel->item->bonds(); rb != NULL; rb = rb->next)
						{
							idj = rb->item->partner(isel->item)->id() - idoff;
							if (idi < idj) continue;
							++count;
							if (!patclip.hasBond(idi,idj))
							{
								same = false;
								break;
							}
						}
						if (!same) break;
					}
					// Check for difference between number of bonds between marked atoms and clipboard atoms
					if (count != patclip.nBonds()) same = false;
				}
			}

			// If we get to here with same == true then we increase nmols. Otherwise, we create a new pattern.
			if (same) ++nmols;
			else
			{
				// Not the same as the last stored pattern, so store old data and start a new one
				Messenger::print(Messenger::Verbose, "New pattern found: %s", qPrintable(empirical));
				p = addPattern(qPrintable(empirical), nmols, patclip.nAtoms());
				patclip.copyMarked(this);
				empirical = selectionEmpirical(true);
				nmols = 1;
			}
		}
	}
	// Store last pattern data 
	if (nmols != 0)
	{
		Messenger::print(Messenger::Verbose, "New pattern found: %s", qPrintable(empirical));
		p = addPattern(qPrintable(empirical), nmols, patclip.nAtoms());
	}

	// Describe the atoms / rings in the patterns
	describeAtoms();

	// Patterns depend only on the properties / relation of the atoms, and not the positions..
	patternsPoint_ = log(Log::Structure);

	Messenger::exit("Model::createPatterns");
	return true;
}