001package org.biopax.paxtools.io.sif.level3;
002
003import org.apache.commons.logging.Log;
004import org.apache.commons.logging.LogFactory;
005import org.biopax.paxtools.controller.ModelUtils;
006import org.biopax.paxtools.model.BioPAXElement;
007import org.biopax.paxtools.model.BioPAXLevel;
008import org.biopax.paxtools.model.Model;
009import org.biopax.paxtools.model.level3.*;
010import org.biopax.paxtools.model.level3.Process;
011
012import java.io.IOException;
013import java.io.OutputStream;
014import java.io.OutputStreamWriter;
015import java.io.Writer;
016import java.util.HashMap;
017import java.util.HashSet;
018import java.util.Map;
019import java.util.Set;
020
021/**
022 * This class analyzes the network to predict the effect of modifications on PEs on their activity.
023 *
024 * NOTE: This method is experimental and makes several assumptions based on the existing data sources.
025 * It might not work universally or return unexpected results for untested data sets. Use with caution.
026 *
027 * @author Emek Demir
028 * @deprecated
029 */
030public class ActivityNetworkAnalyzer
031{
032    private static final Log log = LogFactory.getLog(ActivityNetworkAnalyzer.class);
033
034        Map<BioPAXElement, Set<PEStateChange>> stateChangeMap;
035
036        Map<Conversion, Set<EntityReference>> extendedControls;
037
038        private static final Control EXTENDED;
039
040        static
041        {
042                EXTENDED = BioPAXLevel.L3.getDefaultFactory().create(
043                                Control.class,"http://biopax" + ".org/generated/ExtendedControl");
044                EXTENDED.setControlType(ControlType.ACTIVATION);
045                EXTENDED.addName("Inferred from complex binding");
046        }
047
048        /**
049         * Given a model this method will analyze the states and populate the stateChangeMap and extendedControls maps.
050         * @param model to be analyzed.
051         */
052        public void analyzeStates(Model model)
053        {
054                GroupMap groupMap = Grouper.inferGroups(model);
055                ModelUtils.replaceEquivalentFeatures(model);
056
057                stateChangeMap = new HashMap<BioPAXElement, Set<PEStateChange>>();
058                extendedControls = new HashMap<Conversion, Set<EntityReference>>();
059
060                for (EntityReference pr : model.getObjects(EntityReference.class))
061                {
062                        if (!pr.getRDFId().startsWith("http://biopax.org/generated/fixer/normalizeGenerics/"))
063                        {
064
065                                Set<PEStateChange> stateChanges = stateChangeMap.get(pr);
066                                if (stateChanges == null)
067                                {
068                                        stateChanges = new HashSet<PEStateChange>();
069                                        stateChangeMap.put(pr, stateChanges);
070                                }
071                                for (SimplePhysicalEntity spe : pr.getEntityReferenceOf())
072                                {
073                                        scanInteractions(groupMap, stateChanges, pr, spe);
074
075                                }
076                        }
077                }
078        }
079
080        private void scanInteractions(GroupMap groupMap, Set<PEStateChange> stateChanges, EntityReference pr,
081                        PhysicalEntity spe)
082        {
083                for (Interaction interaction : spe.getParticipantOf())
084                {
085                        if (interaction instanceof Conversion)
086                        {
087                                Simplify.entityHasAChange(pr, (Conversion) interaction, groupMap, stateChanges, extendedControls);
088                        }
089                }
090
091                for (PhysicalEntity generic : spe.getMemberPhysicalEntityOf())
092                {
093
094                        scanInteractions(groupMap, stateChanges, pr, generic);
095                }
096
097                for (Complex complex : spe.getComponentOf())
098                {
099
100                        scanInteractions(groupMap, stateChanges, pr, complex);
101                }
102        }
103
104        /**
105         * @param spe a physical entity but complex
106         * @return all preceding states of a SimplePhysicalEntity. Preceding states are other spes of the
107         * same EntityReference that are converted into this spe in one conversion.
108         */
109        public Set<SimplePhysicalEntity> getPrecedingStates(SimplePhysicalEntity spe)
110        {
111                Set<SimplePhysicalEntity> result = new HashSet<SimplePhysicalEntity>();
112                EntityReference er = spe.getEntityReference();
113                Set<PEStateChange> peStateChanges = stateChangeMap.get(er);
114                for (PEStateChange peStateChange : peStateChanges)
115                {
116                        SimplePhysicalEntity next = peStateChange.changedInto(spe);
117                        if (next != null)
118                        {
119                                result.add(peStateChange.left);
120                        }
121                }
122                return result;
123        }
124
125        public Set<PEStateChange> getAllStates(EntityReference er)
126        {
127                return stateChangeMap.get(er);
128        }
129        /**
130         * @param spe a physical entity but complex
131         * @return all succeeding states of a SimplePhysicalEntity. Preceding states are other spes of the
132         * same EntityReference that this spe is converted into in one conversion.
133         */
134        public Set<SimplePhysicalEntity> getSucceedingStates(SimplePhysicalEntity spe)
135        {
136                Set<SimplePhysicalEntity> result = new HashSet<SimplePhysicalEntity>();
137                EntityReference er = spe.getEntityReference();
138                Set<PEStateChange> peStateChanges = stateChangeMap.get(er);
139                for (PEStateChange peStateChange : peStateChanges)
140                {
141                        SimplePhysicalEntity next = peStateChange.changedFrom(spe);
142                        if (next != null)
143                        {
144                                result.add(peStateChange.left);
145                        }
146                }
147                return result;
148        }
149
150        /**
151         * This method writes out the results of the stateNetworkAnalysis for each detected state change.
152         *
153         * @param out output stream
154         * @throws IOException when an I/O error happens
155         */
156        public void writeStateNetworkAnalysis(OutputStream out) throws IOException
157        {
158                Writer writer = new OutputStreamWriter(out);
159                log.debug("stateChangeMap.size = " + stateChangeMap.values().size());
160                int ineligible = 0;
161                int eligible = 0;
162                for (BioPAXElement bpe : stateChangeMap.keySet())
163                {
164                        if (bpe instanceof ProteinReference)
165                        {
166                                EntityReference er = (EntityReference) bpe;
167                                Set<PEStateChange> sc = stateChangeMap.get(bpe);
168                                for (PEStateChange sChange : sc)
169                                {
170                                        if (isEligibleProteinModification(sChange))
171                                        {
172                                                Set<Pathway> pathwayComponentOf = sChange.getConv().getPathwayComponentOf();
173                                                for (Pathway pathway : pathwayComponentOf)
174                                                {
175                                                        String s = pathway.getName().toString();
176                                                        if (s.isEmpty())
177                                                        {
178                                                                log.debug("Empty name pathway = " + pathway);
179                                                        }
180                                                        writer.write(s + ";");
181                                                }
182                                                writer.write("\t");
183                                                writer.write(sChange.getConv().getName().toString());
184                                                writer.write("\t");
185                                                writer.write(er.getName().toString());
186                                                writer.write("\t");
187                                                writer.write(er.getXref().toString());
188                                                writer.write("\t");
189                                                writer.write(printControls(getDeltaControl(sChange)));
190                                                writer.write("\t");
191                                                writer.write(sChange.getDeltaFeatures().toString());
192                                                writer.write("\t");
193                                                writer.write(sChange.getControllersAsString());
194                                                writer.write("\n");
195
196                                                eligible++;
197                                        } else
198                                        {
199                                                ineligible++;
200                                        }
201
202                                }
203                        } else
204                        {
205                                log.debug("bpe = " + bpe);
206                        }
207
208                }
209                log.debug("ineligible = " + ineligible);
210                log.debug("eligible = " + eligible);
211                writer.flush();
212
213
214        }
215
216        private Map<Control, Boolean> getDeltaControl(PEStateChange sChange)
217        {
218                Map<Control, Boolean> dc = sChange.getDeltaControls();
219                if (!dc.isEmpty() || sChange.getRight() == null)
220                {
221                        return dc;
222                }
223                else
224                {
225                        //Look ahead:
226                        PhysicalEntity rightRoot = sChange.getRightRoot();
227                        for (PEStateChange next : stateChangeMap.get(sChange.getRight().getEntityReference()))
228                        {
229                                if (nextFollows(rightRoot, next))
230                                {
231                                        dc = next.getDeltaControls();
232                                }
233                        }
234                        if (dc.isEmpty())
235                        {
236                                dc = new HashMap<Control, Boolean>();
237                                HashSet<SimplePhysicalEntity> partners = new HashSet<SimplePhysicalEntity>();
238                                Simplify.getSimpleMembers(rightRoot, partners);
239                                for (SimplePhysicalEntity partner : partners)
240                                {
241                                        for (PEStateChange next : stateChangeMap.get(partner.getEntityReference()))
242                                        {
243                                                if (nextFollows(rightRoot, next))
244                                                {
245                                                        Set<EntityReference> xC = extendedControls.get(next.getConv());
246                                                        if (xC != null && xC.contains(sChange.getRight().getEntityReference()))
247                                                        {
248                                                                log.debug("extended");
249                                                                dc.put(EXTENDED, false);
250                                                        }
251                                                }
252                                        }
253
254                                }
255                        }
256                }
257                return dc;
258        }
259
260        private boolean nextFollows(PhysicalEntity rightRoot, PEStateChange next)
261        {
262                return next != null && next.getLeftRoot() != null && next.getLeftRoot().equals(rightRoot);
263        }
264
265        private String printControls(Map<Control, Boolean> dc)
266        {
267                StringBuilder ctString = new StringBuilder();
268                for (Control control : dc.keySet())
269                {
270                        Boolean direction = dc.get(control);
271                        ctString.append(direction ? "Lost activity:" : "Gained activity").append(":").append(
272                                        control.getControlType());
273                        for (Process process : control.getControlled())
274                        {
275                                ctString.append(process.getName()).append(" ,");
276                        }
277                        ctString.append("; ");
278                }
279                return ctString.toString();
280        }
281
282        private boolean isEligibleProteinModification(PEStateChange sChange)
283        {
284                for (EntityFeature ef : sChange.getDeltaFeatures().keySet())
285                {
286                        if (ef instanceof ModificationFeature && !sChange.getDeltaFeatures().get(ef).equals(ChangeType.UNCHANGED))
287                        {
288                                return true;
289                        }
290                }
291                return false;
292        }
293
294
295}