001package org.biopax.paxtools.io.sif.level3; 002 003import org.apache.commons.logging.Log; 004import org.apache.commons.logging.LogFactory; 005import org.biopax.paxtools.io.sif.BinaryInteractionType; 006import org.biopax.paxtools.model.BioPAXElement; 007import org.biopax.paxtools.model.Model; 008import org.biopax.paxtools.model.level3.*; 009import org.biopax.paxtools.model.level3.Process; 010 011import java.util.*; 012 013import static org.biopax.paxtools.io.sif.BinaryInteractionType.METABOLIC_CATALYSIS; 014import static org.biopax.paxtools.io.sif.BinaryInteractionType.STATE_CHANGE; 015 016/** 017 * A controls a conversion which B is at left or right or both. - 018 * Controls.StateChange (B at both sides (one side may be as a member of a 019 * complex), or B is complex) - Controls.MetabolicChange (B at one side only) 020 * @author Ozgun Babur Date: Dec 29, 2007 Time: 1:27:55 AM 021 */ 022public class ControlRule extends InteractionRuleL3Adaptor 023{ 024 /** 025 * Log for logging. 026 */ 027 private final Log log = LogFactory.getLog(ControlRule.class); 028 029 /** 030 * Supported interaction types. 031 */ 032 private static List<BinaryInteractionType> binaryInteractionTypes = 033 Arrays.asList(METABOLIC_CATALYSIS, STATE_CHANGE); 034 035 /** 036 * Option to mine STATE_CHANGE rule. 037 */ 038 private boolean mineStateChange; 039 040 /** 041 * Option to mine METABOLIC_CHANGE rule. 042 */ 043 private boolean mineMetabolicChange; 044 045 /** 046 * Map form the source element to the state change data. 047 */ 048 private HashMap<BioPAXElement, Set<PEStateChange>> stateChanges = new HashMap<BioPAXElement, 049 Set<PEStateChange>>(); 050 051 /** 052 * Initializes options. 053 * @param options options map 054 */ 055 public void initOptionsNotNull(Map options) 056 { 057 mineStateChange = !checkOption(STATE_CHANGE, Boolean.FALSE, options); 058 mineMetabolicChange = !checkOption(METABOLIC_CATALYSIS, Boolean.FALSE, options); 059 } 060 061 /** 062 * When options map is null, then all rules are generated. Otherwise only rules 063 * that are contained in the options map as a key are generated. 064 * @param is3 set to fill in 065 * @param model biopax graph - may be null, has no use here 066 */ 067 public void inferInteractionsFromPE(InteractionSetL3 is3, PhysicalEntity pe, Model model) 068 { 069 BioPAXElement source = is3.getGroupMap().getEntityReferenceOrGroup(pe); 070 for (Interaction inter : pe.getParticipantOf()) 071 { 072 if (inter instanceof Control) 073 { 074 Control cont = (Control) inter; 075 // Iterate over all affected conversions of this control 076 for (Conversion conv : getAffectedConversions(cont, null)) 077 { 078 processConversion(is3, source, cont, conv); 079 } 080 } 081 } 082 } 083 084 /** 085 * Continue inference with the Control and the Conversion. 086 * @param is3 mined interactions 087 * @param source source of interaction 088 * @param cont the control that source is controller 089 * @param conv the conversion that control is controlling 090 */ 091 private void processConversion(InteractionSetL3 is3, BioPAXElement source, Control cont, Conversion conv) 092 { 093 // Collect left and right simple physical entities of conversion in lists 094 Set<BioPAXElement> left = collectEntities(conv.getLeft(), is3); 095 Set<BioPAXElement> right = collectEntities(conv.getRight(), is3); 096 // Detect physical entities which appear on both sides. 097 098 Set<BioPAXElement> intersection = new HashSet<BioPAXElement>(left); 099 intersection.retainAll(right); 100 101 Set<BioPAXElement> union = new HashSet<BioPAXElement>(left); 102 union.addAll(right); 103 104 // Create simple interactions 105 // Try creating a rule for each physical entity in presence list. 106 for (BioPAXElement target : union) 107 { 108 if (source != target) 109 { 110 if (!(target instanceof Group) || !((Group) target).isComplex()) 111 { 112 mineTarget(source, target, is3, cont, conv, intersection); 113 } 114 } 115 } 116 } 117 118 /** 119 * Create the interaction if the target is changing state. 120 * @param source source of interaction 121 * @param target target of interaction 122 * @param is3 mined rules 123 * @param cont the control that source is controller 124 * @param conv the conversion that control is controlling 125 * @param intersection elements that are both at left and right of the conversion 126 */ 127 private void mineTarget(BioPAXElement source, BioPAXElement target, InteractionSetL3 is3, Control cont, 128 Conversion conv, Set<BioPAXElement> intersection) 129 { 130 if (Simplify.entityHasAChange(target, conv, is3.getGroupMap(), stateChanges.get(target))) 131 { 132 133 // If it is simple, then we check if it is also on both sides, regarding the 134 // possibility that it may be nested in a complex. 135 if (intersection.contains(target)) 136 { 137 if (mineStateChange) 138 { 139 createAndAdd(source, target, is3, STATE_CHANGE, cont, conv); 140 } 141 } 142 // Else it is a simple molecule appearing on one side of conversion. This means 143 // it is metabolic change. 144 else 145 { 146 if (mineMetabolicChange) 147 { 148 createAndAdd(source, target, is3, METABOLIC_CATALYSIS, cont, conv); 149 } 150 } 151 } 152 } 153 154 155 /** 156 * Creates a list of conversions on which this control has an effect. If the 157 * control controls another control, then it is traversed recursively to find 158 * the affected conversions. 159 * @param cont control 160 * @param convList list of affected conversions 161 * @return list of affected conversions 162 */ 163 private List<Conversion> getAffectedConversions(Control cont, List<Conversion> convList) 164 { 165 if (convList == null) 166 { 167 convList = new ArrayList<Conversion>(); 168 } 169 for (Process prcss : cont.getControlled()) 170 { 171 if (prcss instanceof Conversion) 172 { 173 convList.add((Conversion) prcss); 174 } else if (prcss instanceof Control) 175 { 176 getAffectedConversions((Control) prcss, convList); 177 } 178 } 179 return convList; 180 } 181 182 /** 183 * Gets supported interaction types. 184 * @return supported interaction types 185 */ 186 public List<BinaryInteractionType> getRuleTypes() 187 { 188 return binaryInteractionTypes; 189 } 190}