All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.biopax.paxtools.io.sif.level2.ControlRule Maven / Gradle / Ivy

Go to download

Converts a BioPAX model to binary SIF (simple interaction format) or extended binary SIF by inferring the interactions in the model and describing them in terms of simple interactions. This includes a set of BioPAX-specific inference rules implemented on top of paxtools-core.

The newest version!
package org.biopax.paxtools.io.sif.level2;

import org.biopax.paxtools.io.sif.BinaryInteractionType;
import org.biopax.paxtools.io.sif.InteractionSet;
import org.biopax.paxtools.io.sif.SimpleInteraction;
import org.biopax.paxtools.model.Model;
import org.biopax.paxtools.model.level2.*;

import java.util.*;

import static org.biopax.paxtools.io.sif.BinaryInteractionType.METABOLIC_CATALYSIS;
import static org.biopax.paxtools.io.sif.BinaryInteractionType.STATE_CHANGE;

/**
 * A controls a conversion which B is at left or right or both. -
 * Controls.StateChange (B at both sides (one side may be as a member of a
 * complex), or B is complex) - Controls.MetabolicChange (B at one side only)
 * @author Ozgun Babur Date: Dec 29, 2007 Time: 1:27:55 AM
 */
public class ControlRule extends InteractionRuleL2Adaptor
{
	/**
	 * Supported interaction types.
	 */
	private static List binaryInteractionTypes =
			Arrays.asList(METABOLIC_CATALYSIS, STATE_CHANGE);

	/**
	 * Option to mine METABOLIC_CHANGE type.
	 */
	private boolean mineMetabolicChange;

	/**
	 * Option to mine STATE_CHANGE type.
	 */
	private boolean mineStateChange;

	/**
	 * Initializes option.
	 * @param options options map
	 */
	@Override public void initOptionsNotNull(Map options)
	{
		mineStateChange = !options.containsKey(STATE_CHANGE) ||
			options.get(STATE_CHANGE).equals(Boolean.TRUE);

		mineMetabolicChange = !options.containsKey(METABOLIC_CATALYSIS) ||
			options.get(METABOLIC_CATALYSIS).equals(Boolean.TRUE);
	}

	/**
	 * When options map is null, then all rules are generated. Otherwise only rules
	 * that are contained in the options map as a key are generated.
	 * @param interactionSet set to fill in
	 * @param A first physical entity
	 * @param model biopax graph - may be null, has no use here
	 */
	public void inferInteractionsFromPE(InteractionSet interactionSet, physicalEntity A, Model model)
	{

		// Iterate over all associated controls

		for (control cont : A.getAllInteractions(control.class))
		{
			// Iterate over all affected conversions of this control

			for (conversion conv : getAffectedConversions(cont, null))
			{
				Set presenceSet = collectEntities(conv.getLEFT(), null);
				collectEntities(conv.getRIGHT(), presenceSet);

				// Collect left and right simple physical entities of conversion in lists

				List left = collectSimpleEntities(conv.getLEFT());
				List right = collectSimpleEntities(conv.getRIGHT());

				// Detect physical entities which appear on both sides.

				List bothsided = new ArrayList();

				for (physicalEntity B : left)
				{
					if (right.contains(B))
					{
						bothsided.add(B);
					}
				}

				// Create simple interactions
				// Try creating a rule for each physical entity in presence list.

				for (physicalEntity B : presenceSet)
				{
					// Consider only molecules that is changed by the conversion
					if (!entityHasAChange(B, conv))
					{
						continue;
					}

					// Affecting a complex is accepted as type of state change.
					// If it is simple, then we check if it is also on both sides, regarding the
					// possibility that it may be nested in a complex.

					if (B instanceof complex || bothsided.contains(B))
					{
						if (mineStateChange)
						{
							SimpleInteraction sc = new SimpleInteraction(A, B, STATE_CHANGE);
							sc.addMediator(cont);
							sc.addMediator(conv);
							interactionSet.add(sc);
						}
					}

					// Else it is a simple molecule appearing on one side of conversion. This means
					// it is metabolic change.

					else
					{
						if (mineMetabolicChange)
						{
							SimpleInteraction mc = new SimpleInteraction(A, B, METABOLIC_CATALYSIS);
							mc.addMediator(cont);
							mc.addMediator(conv);
							interactionSet.add(mc);
						}
					}
				}
			}
		}
	}

	/**
	 * Creates a list of conversions on which this control has an effect. If the
	 * control controls another control, then it is traversed recursively to find
	 * the affected conversions.
	 * @param cont control
	 * @param convList list of affected conversions
	 * @return list of affected conversions
	 */
	private List getAffectedConversions(control cont, List convList)
	{
		if (convList == null)
		{
			convList = new ArrayList();
		}

		for (process prcss : cont.getCONTROLLED())
		{
			if (prcss instanceof conversion)
			{
				convList.add((conversion) prcss);
			} else if (prcss instanceof control)
			{
				getAffectedConversions((control) prcss, convList);
			}
		}

		return convList;
	}

	/**
	 * Collects the associated physical entities of the given participant set.
	 * @param partics participants
	 * @param peSet physical entity set to collect in
	 * @return associated physical entities
	 */
	private Set collectEntities(Set partics, Set peSet)
	{
		if (peSet == null)
		{
			peSet = new HashSet();
		}

		for (physicalEntityParticipant partic : partics)
		{
			peSet.add(partic.getPHYSICAL_ENTITY());
		}

		return peSet;
	}

	/**
	 * Collects the associated non-complex physical entities of the given
	 * participant set. This means we are not interested in complexes, but their
	 * members, at any nesting.
	 * @param partics participants
	 * @return associated physical entities
	 */
	private List collectSimpleEntities(Set partics)
	{
		List peList = new ArrayList();

		for (physicalEntityParticipant partic : partics)
		{
			physicalEntity pe = partic.getPHYSICAL_ENTITY();

			if (pe instanceof complex)
			{
				collectSimpleMembersOfComplex(peList, (complex) pe);
			} else
			{
				peList.add(pe);
			}
		}

		return peList;
	}

	/**
	 * Recursive method for collecting simple members of the given complex in the
	 * given list.
	 * @param list where to collect
	 * @param comp complex to collect members
	 */
	private void collectSimpleMembersOfComplex(List list, complex comp)
	{
		for (physicalEntityParticipant pep : comp.getCOMPONENTS())
		{
			physicalEntity pe = pep.getPHYSICAL_ENTITY();

			if (pe instanceof complex)
			{
				collectSimpleMembersOfComplex(list, (complex) pe);
			} else
			{
				list.add(pe);
			}
		}
	}

	/**
	 * Sometimes an entity is both an input and output to a conversion without any state change.
	 * Normally this phenomena should be modeled using controller property of conversion. In other
	 * cases this method detects entities that goes in and out without any change.
	 * @param entity entity to check
	 * @param conv conversion that the entity is participant
	 * @return true if entity has a change in conversion
	 */
	private boolean entityHasAChange(physicalEntity entity, conversion conv)
	{
		Set leftonly = new HashSet();
		Set rightonly = new HashSet();
		Set both = new HashSet();

		for (physicalEntityParticipant pep : conv.getLEFT())
		{
			if (pep.getPHYSICAL_ENTITY() == entity)
			{
				leftonly.add(new StateWrapper(pep));
			}
		}

		for (physicalEntityParticipant pep : conv.getRIGHT())
		{
			if (pep.getPHYSICAL_ENTITY() == entity)
			{
				StateWrapper sw = new StateWrapper(pep);
				if (leftonly.contains(sw))
				{
					leftonly.remove(sw);
					both.add(sw);
				} else if (!both.contains(sw))
				{
					rightonly.add(sw);
				}
			}
		}

		return !leftonly.isEmpty() || !rightonly.isEmpty();
	}

	/**
	 * Gets supported interaction types.
	 * @return supported interaction types
	 */
	public List getRuleTypes()
	{
		return binaryInteractionTypes;
	}

	/**
	 * This wrapper is used for using state equality of participants in sets.
	 */
	private class StateWrapper
	{
		/**
		 * Wrapped participant.
		 */
		final physicalEntityParticipant pep;

		/**
		 * Constructor with the wrapped participant.
		 * @param pep wrapped participant
		 */
		private StateWrapper(physicalEntityParticipant pep)
		{
			this.pep = pep;
		}

		/**
		 * Generates hash code for the state of the participant.
		 * @return hash code
		 */
		public int hashCode()
		{
			return pep.stateCode();
		}

		/**
		 * Checks if two participants are in equivalent state.
		 * @param obj other participant
		 * @return true if they are in equivalent state
		 */
		public boolean equals(Object obj)
		{
			if (obj instanceof StateWrapper)
			{
				StateWrapper sw = (StateWrapper) obj;

				return pep.isInEquivalentState(sw.pep);
			}

			return false;
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy