Exemplo n.º 1
0
/*
 * Removes an entry from a unit-to-identifier map.
 *
 * Arguments:
 *	map		Pointer to the unit-to-identifier map.
 *	unit		The unit.  May be freed upon return.
 *	encoding	The encoding to be removed.
 * Returns:
 *	UT_SUCCESS	Success.
 */
static ut_status
utimRemove(
    UnitToIdMap* const	map,
    const ut_unit*	unit,
    ut_encoding		encoding)
{
    ut_status		status;
    UnitAndId		targetEntry;
    UnitAndId**		treeEntry;

    assert(map != NULL);
    assert(unit != NULL);

    targetEntry.unit = (ut_unit*)unit;
    treeEntry = tfind(&targetEntry, selectTree(map, encoding), compareUnits);

    if (treeEntry == NULL || *treeEntry == NULL) {
	status = UT_SUCCESS;
    }
    else {
	UnitAndId*	uai = *treeEntry;

	(void)tdelete(uai, selectTree(map, encoding), compareUnits);
	uaiFree(uai);
    }

    return status;
}
Exemplo n.º 2
0
/*
 * Adds an entry to a unit-to-identifier map.
 *
 * Arguments:
 *	map		Pointer to unit-to-identifier map.
 *	unit		The unit.  May be freed upon return.
 *	id		The identifier.  May be freed upon return.
 *	encoding	The ostensible encoding of "id".
 * Returns:
 *	UT_BAD_ARG	"id" is inconsistent with "encoding".
 *	UT_OS		Operating-system error.  See "errno".
 *	UT_EXISTS	"unit" already maps to a different identifier.
 *	UT_SUCCESS	Success.
 */
static ut_status
utimAdd(
    UnitToIdMap* const	map,
    const ut_unit*	unit,
    const char* const	id,
    ut_encoding		encoding)
{
    ut_status		status;

    assert(map != NULL);
    assert(unit != NULL);
    assert(id != NULL);

    if (adjustEncoding(&encoding, id)) {
	status = UT_BAD_ARG;
        ut_set_status(status);
	ut_handle_error_message("Identifier not in given encoding");
    }
    else {
	UnitAndId*	targetEntry = uaiNew(unit, id);

	if (targetEntry != NULL) {
	    void**	rootp = selectTree(map, encoding);

	    UnitAndId**	treeEntry = tsearch(targetEntry, rootp, compareUnits);

	    if (treeEntry == NULL) {
		status = UT_OS;
                ut_set_status(status);
		ut_handle_error_message(strerror(errno));
		ut_handle_error_message("Couldn't add search-tree entry");
		uaiFree(targetEntry);
	    }
	    else {
		if (strcmp((*treeEntry)->id, id) != 0) {
		    status = UT_EXISTS;
                    ut_set_status(status);
		    ut_handle_error_message("Unit already maps to \"%s\"",
			(*treeEntry)->id);
		}
		else {
		    status = UT_SUCCESS;
		}

                if (targetEntry != *treeEntry)
                    uaiFree(targetEntry);
	    }
	}				/* "targetEntry" allocated */
    }					/* valid arguments */

    return status;
}
Exemplo n.º 3
0
/*
 * Frees a unit-to-identifier map.  All entries in all encodings are freed.
 *
 * Arguments:
 *	map		Pointer to the map to be freed.
 */
static void
utimFree(
    UnitToIdMap*	map)
{
    if (map != NULL) {
	ut_encoding	encodings[] = {UT_ASCII, UT_LATIN1, UT_UTF8};
	int		i;

	for (i = 0; i < sizeof(encodings)/sizeof(encodings[0]); ++i) {
	    void**	rootp = selectTree(map, encodings[i]);

	    while (*rootp != NULL) {
		UnitAndId*	uai = **(UnitAndId***)rootp;

		(void)tdelete(uai, rootp, compareUnits);
		uaiFree(uai);
	    }
	}

	free(map);
    }
}
Exemplo n.º 4
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;
}