001package org.biopax.paxtools.pattern;
002
003import org.biopax.paxtools.model.level3.*;
004import org.biopax.paxtools.pattern.constraint.*;
005import org.biopax.paxtools.pattern.util.Blacklist;
006import org.biopax.paxtools.pattern.util.RelType;
007
008import java.util.HashSet;
009import java.util.Map;
010import java.util.Set;
011
012import static org.biopax.paxtools.pattern.constraint.ConBox.*;
013
014/**
015 * This class contains several pattern samples.
016 *
017 * @author Ozgun Babur
018 */
019public class PatternBox
020{
021        //---- Section: Binary interaction patterns ---------------------------------------------------|
022
023        /**
024         * Pattern for a EntityReference has a member PhysicalEntity that is controlling a state change
025         * reaction of another EntityReference.
026         * @return the pattern
027         */
028        public static Pattern controlsStateChange()
029        {
030                Pattern p = new Pattern(SequenceEntityReference.class, "controller ER");
031                p.add(linkedER(true), "controller ER", "generic controller ER");
032                p.add(erToPE(), "generic controller ER", "controller simple PE");
033                p.add(linkToComplex(), "controller simple PE", "controller PE");
034                p.add(peToControl(), "controller PE", "Control");
035                p.add(controlToConv(), "Control", "Conversion");
036                p.add(new NOT(participantER()), "Conversion", "controller ER");
037                p.add(new Participant(RelType.INPUT, true), "Control", "Conversion", "input PE");
038                p.add(linkToSpecific(), "input PE", "input simple PE");
039                p.add(new Type(SequenceEntity.class), "input simple PE");
040                p.add(peToER(), "input simple PE", "changed generic ER");
041                p.add(new ConversionSide(ConversionSide.Type.OTHER_SIDE), "input PE", "Conversion", "output PE");
042                p.add(equal(false), "input PE", "output PE");
043                p.add(linkToSpecific(), "output PE", "output simple PE");
044                p.add(peToER(), "output simple PE", "changed generic ER");
045                p.add(linkedER(false), "changed generic ER", "changed ER");
046
047                return p;
048        }
049
050        /**
051         * Pattern for a ProteinReference has a member PhysicalEntity that is controlling a
052         * transportation of another ProteinReference.
053         * @return the pattern
054         */
055        public static Pattern controlsTransport()
056        {
057                Pattern p = controlsStateChange();
058                p.add(new OR(
059                        new MappedConst(hasDifferentCompartments(), 0, 1),
060                        new MappedConst(hasDifferentCompartments(), 2, 3)),
061                        "input simple PE", "output simple PE", "input PE", "output PE");
062
063                return p;
064        }
065
066        /**
067         * Pattern for a ProteinReference has a member PhysicalEntity that is controlling a reaction
068         * that changes cellular location of a small molecule.
069         *
070         * @param blacklist a skip-list of ubiquitous molecules
071         * @return the pattern
072         */
073        public static Pattern controlsTransportOfChemical(Blacklist blacklist)
074        {
075                Pattern p = new Pattern(SequenceEntityReference.class, "controller ER");
076                p.add(linkedER(true), "controller ER", "controller generic ER");
077                p.add(erToPE(), "controller generic ER", "controller simple PE");
078                p.add(linkToComplex(), "controller simple PE", "controller PE");
079                p.add(peToControl(), "controller PE", "Control");
080                p.add(controlToConv(), "Control", "Conversion");
081                p.add(new Participant(RelType.INPUT, blacklist, true), "Control", "Conversion", "input PE");
082                p.add(linkToSimple(blacklist), "input PE", "input simple PE");
083                p.add(new Type(SmallMolecule.class), "input simple PE");
084                p.add(notGeneric(), "input simple PE");
085                p.add(peToER(), "input simple PE", "changed generic SMR");
086                p.add(new ConversionSide(ConversionSide.Type.OTHER_SIDE, blacklist, RelType.OUTPUT), "input PE", "Conversion", "output PE");
087                p.add(equal(false), "input PE", "output PE");
088                p.add(linkToSimple(blacklist), "output PE", "output simple PE");
089                p.add(new Type(SmallMolecule.class), "output simple PE");
090                p.add(notGeneric(), "output simple PE");
091                p.add(peToER(), "output simple PE", "changed generic SMR");
092                p.add(linkedER(false), "changed generic SMR", "changed SMR");
093                p.add(new OR(
094                        new MappedConst(hasDifferentCompartments(), 0, 1),
095                        new MappedConst(hasDifferentCompartments(), 2, 3)),
096                        "input simple PE", "output simple PE", "input PE", "output PE");
097
098                return p;
099        }
100
101        /**
102         * Pattern for a EntityReference has a member PhysicalEntity that is controlling a state change
103         * reaction of another EntityReference. In this case the controller is also an input to the
104         * reaction. The affected protein is the one that is represented with different non-generic
105         * physical entities at left and right of the reaction.
106         * @return the pattern
107         */
108        public static Pattern controlsStateChangeBothControlAndPart()
109        {
110                Pattern p = new Pattern(SequenceEntityReference.class, "controller ER");
111                p.add(linkedER(true), "controller ER", "controller generic ER");
112                p.add(erToPE(), "controller generic ER", "controller simple PE");
113                p.add(linkToComplex(), "controller simple PE", "controller PE");
114                p.add(peToControl(), "controller PE", "Control");
115                p.add(controlToConv(), "Control", "Conversion");
116
117                // the controller PE is also an input
118                p.add(new ParticipatesInConv(RelType.INPUT), "controller PE", "Conversion");
119
120                // same controller simple PE is also an output
121                p.add(linkToComplex(), "controller simple PE", "special output PE");
122                p.add(equal(false), "special output PE", "controller PE");
123                p.add(new ParticipatesInConv(RelType.OUTPUT), "special output PE", "Conversion");
124
125                stateChange(p, "Control");
126
127                // non-generic input and outputs are only associated with one side
128                p.add(equal(false), "input simple PE", "output simple PE");
129                p.add(new NOT(simplePEToConv(RelType.OUTPUT)), "input simple PE", "Conversion");
130                p.add(new NOT(simplePEToConv(RelType.INPUT)), "output simple PE", "Conversion");
131
132                p.add(equal(false), "controller ER", "changed ER");
133                p.add(type(SequenceEntityReference.class), "changed ER");
134
135                return p;
136        }
137
138        /**
139         * Pattern for a EntityReference has a member PhysicalEntity that is controlling a state change
140         * reaction of another EntityReference. This pattern is different from the original
141         * controls-state-change. The controller in this case is not modeled as a controller, but as a
142         * participant of the conversion, and it is at both sides.
143         * @return the pattern
144         */
145        public static Pattern controlsStateChangeButIsParticipant()
146        {
147                Pattern p = new Pattern(SequenceEntityReference.class, "controller ER");
148                p.add(linkedER(true), "controller ER", "controller generic ER");
149                p.add(erToPE(), "controller generic ER", "controller simple PE");
150                p.add(linkToComplex(), "controller simple PE", "controller PE");
151                p.add(participatesInConv(), "controller PE", "Conversion");
152                p.add(left(), "Conversion", "controller PE");
153                p.add(right(), "Conversion", "controller PE");
154                // The controller ER is not associated with the Conversion in another way.
155                p.add(new NOT(new InterToPartER(1)), "Conversion", "controller PE", "controller ER");
156
157                stateChange(p, null);
158
159                p.add(equal(false), "controller ER", "changed ER");
160                p.add(equal(false), "controller PE", "input PE");
161                p.add(equal(false), "controller PE", "output PE");
162
163                return p;
164        }
165
166        /**
167         * Pattern for a Conversion has an input PhysicalEntity and another output PhysicalEntity that
168         * belongs to the same EntityReference.
169         *
170         * @param p pattern to update
171         * @param ctrlLabel label
172         * @return the pattern
173         */
174        public static Pattern stateChange(Pattern p, String ctrlLabel)
175        {
176                if (p == null) p = new Pattern(Conversion.class, "Conversion");
177
178                if (ctrlLabel == null) p.add(new Participant(RelType.INPUT), "Conversion", "input PE");
179                else p.add(new Participant(RelType.INPUT, true), ctrlLabel, "Conversion", "input PE");
180
181                p.add(linkToSpecific(), "input PE", "input simple PE");
182                p.add(peToER(), "input simple PE", "changed generic ER");
183                p.add(new ConversionSide(ConversionSide.Type.OTHER_SIDE), "input PE", "Conversion", "output PE");
184                p.add(equal(false), "input PE", "output PE");
185                p.add(linkToSpecific(), "output PE", "output simple PE");
186                p.add(peToER(), "output simple PE", "changed generic ER");
187                p.add(linkedER(false), "changed generic ER", "changed ER");
188                return p;
189        }
190
191        /**
192         * Pattern for an entity is producing a small molecule, and the small molecule controls state
193         * change of another molecule.
194         *
195         * @param blacklist a skip-list of ubiquitous molecules
196         * @return the pattern
197         */
198        public static Pattern controlsStateChangeThroughControllerSmallMolecule(Blacklist blacklist)
199        {
200                Pattern p = new Pattern(SequenceEntityReference.class, "upper controller ER");
201                p.add(linkedER(true), "upper controller ER", "upper controller generic ER");
202                p.add(erToPE(), "upper controller generic ER", "upper controller simple PE");
203                p.add(linkToComplex(), "upper controller simple PE", "upper controller PE");
204                p.add(peToControl(), "upper controller PE", "upper Control");
205                p.add(controlToConv(), "upper Control", "upper Conversion");
206                p.add(new NOT(participantER()), "upper Conversion", "upper controller ER");
207                p.add(new Participant(RelType.OUTPUT, blacklist), "upper Conversion", "controller PE");
208                p.add(type(SmallMolecule.class), "controller PE");
209                if (blacklist != null) p.add(new NonUbique(blacklist), "controller PE");
210
211                // the linker small mol is at also an input
212                p.add(new NOT(new ConstraintChain(
213                        new ConversionSide(ConversionSide.Type.OTHER_SIDE), linkToSpecific())),
214                        "controller PE", "upper Conversion", "controller PE");
215
216                p.add(peToControl(), "controller PE", "Control");
217                p.add(controlToConv(), "Control", "Conversion");
218                p.add(equal(false), "upper Conversion", "Conversion");
219
220//              p.add(nextInteraction(), "upper Conversion", "Conversion");
221
222                stateChange(p, "Control");
223
224                p.add(type(SequenceEntityReference.class), "changed ER");
225                p.add(equal(false), "upper controller ER", "changed ER");
226                p.add(new NOT(participantER()), "Conversion", "upper controller ER");
227
228                return p;
229        }
230
231        /**
232         * Pattern for an entity is producing a small molecule, and the small molecule controls state
233         * change of another molecule.
234         *
235         * @param blacklist a skip-list of ubiquitous molecules
236         * @return the pattern
237         */
238        public static Pattern controlsStateChangeThroughBindingSmallMolecule(Blacklist blacklist)
239        {
240                Pattern p = new Pattern(SequenceEntityReference.class, "upper controller ER");
241                p.add(linkedER(true), "upper controller ER", "upper controller generic ER");
242                p.add(erToPE(), "upper controller ER", "upper controller simple PE");
243                p.add(linkToComplex(), "upper controller simple PE", "upper controller PE");
244                p.add(peToControl(), "upper controller PE", "upper Control");
245                p.add(controlToConv(), "upper Control", "upper Conversion");
246                p.add(new NOT(participantER()), "upper Conversion", "upper controller ER");
247                p.add(new Participant(RelType.OUTPUT, blacklist, true), "upper Control", "upper Conversion", "SM");
248                p.add(type(SmallMolecule.class), "SM");
249                if (blacklist != null) p.add(new NonUbique(blacklist), "SM");
250
251                // the linker small mol is at also an input
252                p.add(new NOT(new ConstraintChain(
253                        new ConversionSide(ConversionSide.Type.OTHER_SIDE), linkToSpecific())),
254                        "SM", "upper Conversion", "SM");
255
256                p.add(new ParticipatesInConv(RelType.INPUT), "SM", "Conversion");
257                p.add(peToER(), "SM", "SM ER");
258                p.add(equal(false), "upper Conversion", "Conversion");
259
260//              p.add(nextInteraction(), "upper Conversion", "Conversion");
261
262                stateChange(p, null);
263
264                p.add(type(SequenceEntityReference.class), "changed ER");
265                p.add(equal(false), "upper controller ER", "changed ER");
266                p.add(new NOT(participantER()), "Conversion", "upper controller ER");
267                p.add(compToER(), "output PE", "SM ER");
268
269                return p;
270        }
271
272        /**
273         * Finds cases where proteins affect their degradation.
274         * @return the pattern
275         */
276        public static Pattern controlsStateChangeThroughDegradation()
277        {
278                Pattern p = new Pattern(SequenceEntityReference.class, "upstream ER");
279                p.add(linkedER(true), "upstream ER", "upstream generic ER");
280                p.add(erToPE(), "upstream generic ER", "upstream SPE");
281                p.add(linkToComplex(), "upstream SPE", "upstream PE");
282                p.add(peToControl(), "upstream PE", "Control");
283                p.add(controlToConv(), "Control", "Conversion");
284                p.add(new NOT(participantER()), "Conversion", "upstream ER");
285                p.add(new Empty(new Participant(RelType.OUTPUT)), "Conversion");
286                p.add(new Participant(RelType.INPUT), "Conversion", "input PE");
287                p.add(linkToSpecific(), "input PE", "input SPE");
288                p.add(peToER(), "input SPE", "downstream generic ER");
289                p.add(type(SequenceEntityReference.class), "downstream generic ER");
290                p.add(linkedER(false), "downstream generic ER", "downstream ER");
291                return p;
292        }
293
294        public static Pattern controlsPhosphorylation()
295        {
296                Pattern p = controlsStateChange();
297                p.add(new NOT(ConBox.linkToSpecific()), "input PE", "output simple PE");
298                p.add(new NOT(ConBox.linkToSpecific()), "output PE", "input simple PE");
299                p.add(new ModificationChangeConstraint(ModificationChangeConstraint.Type.ANY,
300                        "phospho"), "input simple PE", "output simple PE");
301                return p;
302        }
303
304        /**
305         * Pattern for a Protein controlling a reaction whose participant is a small molecule.
306         *
307         * @param blacklist a skip-list of ubiquitous molecules
308         * @param consumption true/false (TODO explain)
309         * @return the pattern
310         */
311        public static Pattern controlsMetabolicCatalysis(Blacklist blacklist, boolean consumption)
312        {
313                Pattern p = new Pattern(SequenceEntityReference.class, "controller ER");
314                p.add(linkedER(true), "controller ER", "controller generic ER");
315                p.add(erToPE(), "controller generic ER", "controller simple PE");
316                p.add(linkToComplex(), "controller simple PE", "controller PE");
317                p.add(peToControl(), "controller PE", "Control");
318                p.add(controlToConv(), "Control", "Conversion");
319                p.add(new NOT(participantER()), "Conversion", "controller ER");
320
321                p.add(new Participant(consumption ? RelType.INPUT : RelType.OUTPUT, blacklist, true),
322                        "Control", "Conversion", "part PE");
323
324                p.add(linkToSimple(blacklist), "part PE", "part SM");
325                p.add(notGeneric(), "part SM");
326                p.add(type(SmallMolecule.class), "part SM");
327                p.add(peToER(), "part SM", "part SMR");
328
329                // The small molecule is associated only with left or right, but not both.
330                p.add(new XOR(
331                        new MappedConst(new InterToPartER(InterToPartER.Direction.LEFT), 0, 1),
332                        new MappedConst(new InterToPartER(InterToPartER.Direction.RIGHT), 0, 1)),
333                        "Conversion", "part SMR");
334
335                return p;
336        }
337
338
339        /**
340         * Pattern for detecting two EntityReferences are controlling consecutive reactions, where
341         * output of one reaction is input to the other.
342         *
343         * @param blacklist to detect ubiquitous small molecules
344         * @return the pattern
345         */
346        public static Pattern catalysisPrecedes(Blacklist blacklist)
347        {
348                Pattern p = new Pattern(SequenceEntityReference.class, "first ER");
349                p.add(linkedER(true), "first ER", "first generic ER");
350                p.add(erToPE(), "first generic ER", "first simple controller PE");
351                p.add(linkToComplex(), "first simple controller PE", "first controller PE");
352                p.add(peToControl(), "first controller PE", "first Control");
353                p.add(controlToConv(), "first Control", "first Conversion");
354                p.add(new Participant(RelType.OUTPUT, blacklist, true), "first Control", "first Conversion", "linker PE");
355                p.add(new NOT(new ConstraintChain(new ConversionSide(ConversionSide.Type.OTHER_SIDE), linkToSpecific())), "linker PE", "first Conversion", "linker PE");
356                p.add(type(SmallMolecule.class), "linker PE");
357                p.add(new ParticipatesInConv(RelType.INPUT, blacklist), "linker PE", "second Conversion");
358                p.add(new NOT(new ConstraintChain(new ConversionSide(ConversionSide.Type.OTHER_SIDE), linkToSpecific())), "linker PE", "second Conversion", "linker PE");
359                p.add(equal(false), "first Conversion", "second Conversion");
360
361                // make sure that conversions are not replicates or reverse of each other
362                // and also outward facing sides of reactions contain at least one non ubique
363                p.add(new ConstraintAdapter(3, blacklist)
364                {
365                        @Override
366                        public boolean satisfies(Match match, int... ind)
367                        {
368                                Conversion cnv1 = (Conversion) match.get(ind[0]);
369                                Conversion cnv2 = (Conversion) match.get(ind[1]);
370                                SmallMolecule linker = (SmallMolecule) match.get(ind[2]);
371
372                                Set<PhysicalEntity> input1 = cnv1.getLeft().contains(linker) ? cnv1.getRight() : cnv1.getLeft();
373                                Set<PhysicalEntity> input2 = cnv2.getLeft().contains(linker) ? cnv2.getLeft() : cnv2.getRight();
374                                Set<PhysicalEntity> output1 = cnv1.getLeft().contains(linker) ? cnv1.getLeft() : cnv1.getRight();
375                                Set<PhysicalEntity> output2 = cnv2.getLeft().contains(linker) ? cnv2.getRight() : cnv2.getLeft();
376
377                                if (input1.equals(input2) && output1.equals(output2)) return false;
378                                if (input1.equals(output2) && output1.equals(input2)) return false;
379
380                                if (blacklist != null)
381                                {
382                                        Set<PhysicalEntity> set = new HashSet<PhysicalEntity>(input1);
383                                        set = blacklist.getNonUbiques(set, RelType.INPUT);
384                                        set.removeAll(output2);
385                                        if (set.isEmpty())
386                                        {
387                                                set.addAll(output2);
388                                                set = blacklist.getNonUbiques(set, RelType.OUTPUT);
389                                                set.removeAll(input1);
390
391                                                if (set.isEmpty()) return false;
392                                        }
393                                }
394                                return true;
395                        }
396                }, "first Conversion", "second Conversion", "linker PE");
397
398                p.add(new RelatedControl(RelType.INPUT, blacklist), "linker PE", "second Conversion", "second Control");
399                p.add(controllerPE(), "second Control", "second controller PE");
400                p.add(new NOT(compToER()), "second controller PE", "first ER");
401                p.add(linkToSpecific(), "second controller PE", "second simple controller PE");
402                p.add(type(SequenceEntity.class), "second simple controller PE");
403                p.add(peToER(), "second simple controller PE", "second generic ER");
404                p.add(linkedER(false), "second generic ER", "second ER");
405                p.add(equal(false), "first ER", "second ER");
406                return p;
407        }
408
409        /**
410         * Finds transcription factors that trans-activate or trans-inhibit an entity.
411         * @return the pattern
412         */
413        public static Pattern controlsExpressionWithTemplateReac()
414        {
415                Pattern p = new Pattern(SequenceEntityReference.class, "TF ER");
416                p.add(linkedER(true), "TF ER", "TF generic ER");
417                p.add(erToPE(), "TF generic ER", "TF SPE");
418                p.add(linkToComplex(), "TF SPE", "TF PE");
419                p.add(peToControl(), "TF PE", "Control");
420                p.add(controlToTempReac(), "Control", "TempReac");
421                p.add(product(), "TempReac", "product PE");
422                p.add(linkToSpecific(), "product PE", "product SPE");
423                p.add(new Type(SequenceEntity.class), "product SPE");
424                p.add(peToER(), "product SPE", "product generic ER");
425                p.add(linkedER(false), "product generic ER", "product ER");
426                p.add(equal(false), "TF ER", "product ER");
427                return p;
428        }
429
430        /**
431         * Finds the cases where transcription relation is shown using a Conversion instead of a
432         * TemplateReaction.
433         * @return the pattern
434         */
435        public static Pattern controlsExpressionWithConversion()
436        {
437                Pattern p = new Pattern(SequenceEntityReference.class, "TF ER");
438                p.add(linkedER(true), "TF ER", "TF generic ER");
439                p.add(erToPE(), "TF generic ER", "TF SPE");
440                p.add(linkToComplex(), "TF SPE", "TF PE");
441                p.add(peToControl(), "TF PE", "Control");
442                p.add(controlToConv(), "Control", "Conversion");
443                p.add(new Size(right(), 1, Size.Type.EQUAL), "Conversion");
444                p.add(new OR(new MappedConst(new Empty(left()), 0), new MappedConst(new ConstraintAdapter(1)
445                {
446                        @Override
447                        public boolean satisfies(Match match, int... ind)
448                        {
449                                Conversion cnv = (Conversion) match.get(ind[0]);
450                                Set<PhysicalEntity> left = cnv.getLeft();
451                                if (left.size() > 1) return false;
452                                if (left.isEmpty()) return true;
453                                PhysicalEntity pe = left.iterator().next();
454                                if (pe instanceof NucleicAcid)
455                                {
456                                        PhysicalEntity rPE = cnv.getRight().iterator().next();
457                                        return rPE instanceof Protein;
458                                }
459                                return false;
460                        }
461                }, 0)), "Conversion");
462                p.add(right(), "Conversion", "right PE");
463                p.add(linkToSpecific(), "right PE", "right SPE");
464                p.add(new Type(SequenceEntity.class), "right SPE");
465                p.add(peToER(), "right SPE", "product generic ER");
466                p.add(linkedER(false), "product generic ER", "product ER");
467                p.add(equal(false), "TF ER", "product ER");
468                return p;
469        }
470
471        /**
472         * Finds cases where protein A changes state of B, and B is then degraded.
473         *
474         * NOTE: THIS PATTERN DOES NOT WORK. KEEPING ONLY FOR HISTORICAL REASONS.
475         *
476         * @return the pattern
477         */
478        public static Pattern controlsDegradationIndirectly()
479        {
480                Pattern p = controlsStateChange();
481                p.add(new Size(new ParticipatesInConv(RelType.INPUT), 1, Size.Type.EQUAL), "output PE");
482                p.add(new Empty(peToControl()), "output PE");
483                p.add(new ParticipatesInConv(RelType.INPUT), "output PE", "degrading Conv");
484                p.add(new NOT(type(ComplexAssembly.class)), "degrading Conv");
485                p.add(new Size(participant(), 1, Size.Type.EQUAL), "degrading Conv");
486                p.add(new Empty(new Participant(RelType.OUTPUT)), "degrading Conv");
487                p.add(new Empty(convToControl()), "degrading Conv");
488                p.add(equal(false), "degrading Conv", "Conversion");
489                return p;
490        }
491
492        /**
493         * Two proteins have states that are members of the same complex. Handles nested complexes and
494         * homologies. Also guarantees that relationship to the complex is through different direct
495         * complex members.
496         * @return pattern
497         */
498        public static Pattern inComplexWith()
499        {
500                Pattern p = new Pattern(SequenceEntityReference.class, "Protein 1");
501                p.add(linkedER(true), "Protein 1", "generic Protein 1");
502                p.add(erToPE(), "generic Protein 1", "SPE1");
503                p.add(linkToComplex(), "SPE1", "PE1");
504                p.add(new PathConstraint("PhysicalEntity/componentOf"), "PE1", "Complex");
505                p.add(new PathConstraint("Complex/component"), "Complex", "PE2");
506                p.add(equal(false), "PE1", "PE2");
507                p.add(linkToSpecific(), "PE2", "SPE2");
508                p.add(peToER(), "SPE2", "generic Protein 2");
509                p.add(linkedER(false), "generic Protein 2", "Protein 2");
510                p.add(equal(false), "Protein 1", "Protein 2");
511                p.add(new Type(ProteinReference.class), "Protein 2");
512                return p;
513        }
514
515        /**
516         * A small molecule is in a complex with a protein.
517         *
518         * @param blacklist a skip-list of ubiquitous molecules
519         * @return pattern
520         */
521        public static Pattern chemicalAffectsProteinThroughBinding(Blacklist blacklist)
522        {
523                Pattern p = new Pattern(SmallMoleculeReference.class, "SMR");
524                p.add(erToPE(), "SMR", "SPE1");
525                p.add(notGeneric(), "SPE1");
526                if (blacklist != null) p.add(new NonUbique(blacklist), "SPE1");
527                p.add(linkToComplex(), "SPE1", "PE1");
528                p.add(new PathConstraint("PhysicalEntity/componentOf"), "PE1", "Complex");
529                p.add(new PathConstraint("Complex/component"), "Complex", "PE2");
530                p.add(equal(false), "PE1", "PE2");
531                p.add(linkToSpecific(), "PE2", "SPE2");
532                p.add(new Type(SequenceEntity.class), "SPE2");
533                p.add(peToER(), "SPE2", "generic ER");
534                p.add(linkedER(false), "generic ER", "ER");
535                return p;
536        }
537
538        /**
539         * A small molecule controls an interaction of which the protein is a participant.
540         * @return pattern
541         */
542        public static Pattern chemicalAffectsProteinThroughControl()
543        {
544                Pattern p = new Pattern(SmallMoleculeReference.class, "controller SMR");
545                p.add(erToPE(), "controller SMR", "controller simple PE");
546                p.add(notGeneric(), "controller simple PE");
547                p.add(linkToComplex(), "controller simple PE", "controller PE");
548                p.add(peToControl(), "controller PE", "Control");
549                p.add(controlToInter(), "Control", "Interaction");
550                p.add(new NOT(participantER()), "Interaction", "controller SMR");
551                p.add(participant(), "Interaction", "affected PE");
552                p.add(linkToSpecific(), "affected PE", "affected simple PE");
553                p.add(new Type(SequenceEntity.class), "affected simple PE");
554                p.add(peToER(), "affected simple PE", "affected generic ER");
555                p.add(linkedER(false), "affected generic ER", "affected ER");
556                return p;
557        }
558
559        /**
560         * Constructs a pattern where first and last proteins are related through an interaction. They
561         * can be participants or controllers. No limitation.
562         * @return the pattern
563         */
564        public static Pattern neighborOf()
565        {
566                Pattern p = new Pattern(SequenceEntityReference.class, "Protein 1");
567                p.add(linkedER(true), "Protein 1", "generic Protein 1");
568                p.add(erToPE(), "generic Protein 1", "SPE1");
569                p.add(linkToComplex(), "SPE1", "PE1");
570                p.add(peToInter(), "PE1", "Inter");
571                p.add(interToPE(), "Inter", "PE2");
572                p.add(linkToSpecific(), "PE2", "SPE2");
573                p.add(equal(false), "SPE1", "SPE2");
574                p.add(type(SequenceEntity.class), "SPE2");
575                p.add(peToER(), "SPE2", "generic Protein 2");
576                p.add(linkedER(false), "generic Protein 2", "Protein 2");
577                p.add(equal(false), "Protein 1", "Protein 2");
578                return p;
579        }
580
581        /**
582         * Constructs a pattern where first and last small molecules are substrates to the same
583         * biochemical reaction.
584         *
585         * @param blacklist a skip-list of ubiquitous molecules
586         * @return the pattern
587         */
588        public static Pattern reactsWith(Blacklist blacklist)
589        {
590                Pattern p = new Pattern(SmallMoleculeReference.class, "SMR1");
591                p.add(erToPE(), "SMR1", "SPE1");
592                p.add(notGeneric(), "SPE1");
593                p.add(linkToComplex(blacklist), "SPE1", "PE1");
594                p.add(new ParticipatesInConv(RelType.INPUT, blacklist), "PE1", "Conv");
595                p.add(type(BiochemicalReaction.class), "Conv");
596                p.add(new InterToPartER(InterToPartER.Direction.ONESIDERS), "Conv", "SMR1");
597                p.add(new ConversionSide(ConversionSide.Type.SAME_SIDE, blacklist, RelType.INPUT), "PE1", "Conv", "PE2");
598                p.add(type(SmallMolecule.class), "PE2");
599                p.add(linkToSpecific(), "PE2", "SPE2");
600                p.add(notGeneric(), "SPE2");
601                p.add(new PEChainsIntersect(false), "SPE1", "PE1", "SPE2", "PE2");
602                p.add(peToER(), "SPE2", "SMR2");
603                p.add(equal(false), "SMR1", "SMR2");
604                p.add(new InterToPartER(InterToPartER.Direction.ONESIDERS), "Conv", "SMR2");
605                return p;
606        }
607
608        /**
609         * Constructs a pattern where first small molecule is an input a biochemical reaction that
610         * produces the second small molecule.
611         * biochemical reaction.
612         *
613         * @param blacklist a skip-list of ubiquitous molecules
614         * @return the pattern
615         */
616        public static Pattern usedToProduce(Blacklist blacklist)
617        {
618                Pattern p = new Pattern(SmallMoleculeReference.class, "SMR1");
619                p.add(erToPE(), "SMR1", "SPE1");
620                p.add(notGeneric(), "SPE1");
621                p.add(linkToComplex(blacklist), "SPE1", "PE1");
622                p.add(new ParticipatesInConv(RelType.INPUT, blacklist), "PE1", "Conv");
623                p.add(type(BiochemicalReaction.class), "Conv");
624                p.add(new InterToPartER(InterToPartER.Direction.ONESIDERS), "Conv", "SMR1");
625                p.add(new ConversionSide(ConversionSide.Type.OTHER_SIDE, blacklist, RelType.OUTPUT), "PE1", "Conv", "PE2");
626                p.add(type(SmallMolecule.class), "PE2");
627                p.add(linkToSimple(blacklist), "PE2", "SPE2");
628                p.add(notGeneric(), "SPE2");
629                p.add(equal(false), "SPE1", "SPE2");
630                p.add(peToER(), "SPE2", "SMR2");
631                p.add(equal(false), "SMR1", "SMR2");
632                p.add(new InterToPartER(InterToPartER.Direction.ONESIDERS), "Conv", "SMR2");
633                return p;
634        }
635
636        /**
637         * Constructs a pattern where first and last molecules are participants of a
638         * MolecularInteraction.
639         * @return the pattern
640         */
641        public static Pattern molecularInteraction()
642        {
643                Pattern p = new Pattern(SequenceEntityReference.class, "Protein 1");
644                p.add(linkedER(true), "Protein 1", "generic Protein 1");
645                p.add(erToPE(), "generic Protein 1", "SPE1");
646                p.add(linkToComplex(), "SPE1", "PE1");
647                p.add(new PathConstraint("PhysicalEntity/participantOf:MolecularInteraction"), "PE1", "MI");
648                p.add(participant(), "MI", "PE2");
649                p.add(equal(false), "PE1", "PE2");
650
651                // participants are not both baits or preys
652                p.add(new NOT(new AND(new MappedConst(isPrey(), 0), new MappedConst(isPrey(), 1))), "PE1", "PE2");
653                p.add(new NOT(new AND(new MappedConst(isBait(), 0), new MappedConst(isBait(), 1))), "PE1", "PE2");
654
655                p.add(linkToSpecific(), "PE2", "SPE2");
656                p.add(type(SequenceEntity.class), "SPE2");
657                p.add(new PEChainsIntersect(false), "SPE1", "PE1", "SPE2", "PE2");
658                p.add(peToER(), "SPE2", "generic Protein 2");
659                p.add(linkedER(false), "generic Protein 2", "Protein 2");
660                p.add(equal(false), "Protein 1", "Protein 2");
661                return p;
662        }
663
664
665        //----- Section: Other patterns ---------------------------------------------------------------|
666
667        /**
668         * Finds ProteinsReference related to an interaction. If specific types of interactions are
669         * desired, they should be sent as parameter, otherwise leave the parameter empty.
670         *
671         * @param seedType specific BioPAX interaction sub-types (interface classes)
672         * @return pattern
673         */
674        public static Pattern relatedProteinRefOfInter(Class<? extends Interaction>... seedType)
675        {
676                Pattern p = new Pattern(Interaction.class, "Interaction");
677
678                if (seedType.length == 1)
679                {
680                        p.add(new Type(seedType[0]), "Interaction");
681                }
682                else if (seedType.length > 1)
683                {
684                        MappedConst[] mc = new MappedConst[seedType.length];
685                        for (int i = 0; i < mc.length; i++)
686                        {
687                                mc[i] = new MappedConst(new Type(seedType[i]), 0);
688                        }
689
690                        p.add(new OR(mc), "Interaction");
691                }
692
693                p.add(new OR(new MappedConst(participant(), 0, 1),
694                        new MappedConst(new PathConstraint(
695                                "Interaction/controlledOf*/controller:PhysicalEntity"), 0, 1)),
696                        "Interaction", "PE");
697
698                p.add(linkToSpecific(), "PE", "SPE");
699                p.add(peToER(), "SPE", "generic PR");
700                p.add(new Type(ProteinReference.class), "generic PR");
701                p.add(linkedER(false), "generic PR", "PR");
702                return p;
703        }
704
705        /**
706         * Pattern for two different EntityReference have member PhysicalEntity in the same Complex.
707         * Complex membership can be through multiple nesting and/or through homology relations.
708         * @return the pattern
709         */
710        public static Pattern inSameComplex()
711        {
712                Pattern p = new Pattern(EntityReference.class, "first ER");
713                p.add(erToPE(), "first ER", "first simple PE");
714                p.add(linkToComplex(), "first simple PE", "Complex");
715                p.add(new Type(Complex.class), "Complex");
716                p.add(linkToSpecific(), "Complex", "second simple PE");
717                p.add(equal(false), "first simple PE", "second simple PE");
718                p.add(new PEChainsIntersect(false, true), "first simple PE", "Complex", "second simple PE", "Complex");
719                p.add(peToER(), "second simple PE", "second ER");
720                p.add(equal(false), "first ER", "second ER");
721                return p;
722        }
723
724        /**
725         * Pattern for two different EntityReference have member PhysicalEntity in the same Complex, and
726         * the Complex has an activity. Complex membership can be through multiple nesting and/or
727         * through homology relations.
728         * @return the pattern
729         */
730        public static Pattern inSameActiveComplex()
731        {
732                Pattern p = inSameComplex();
733                p.add(new ActivityConstraint(true), "Complex");
734                return p;
735        }
736
737        /**
738         * Pattern for two different EntityReference have member PhysicalEntity in the same Complex, and
739         * the Complex has transcriptional activity. Complex membership can be through multiple nesting
740         * and/or through homology relations.
741         * @return the pattern
742         */
743        public static Pattern inSameComplexHavingTransActivity()
744        {
745                Pattern p = inSameComplex();
746
747                p.add(peToControl(), "Complex", "Control");
748                p.add(controlToTempReac(), "Control", "TR");
749                p.add(new NOT(participantER()), "TR", "first ER");
750                p.add(new NOT(participantER()), "TR", "second ER");
751                return p;
752        }
753
754        /**
755         * Pattern for two different EntityReference have member PhysicalEntity in the same Complex, and
756         * the Complex is controlling a Conversion. Complex membership can be through multiple nesting
757         * and/or through homology relations.
758         * @return the pattern
759         */
760        public static Pattern inSameComplexEffectingConversion()
761        {
762                Pattern p = inSameComplex();
763
764                p.add(peToControl(), "Complex", "Control");
765                p.add(controlToConv(), "Control", "Conversion");
766                p.add(new NOT(participantER()), "Control", "first ER");
767                p.add(new NOT(participantER()), "Control", "second ER");
768                return p;
769        }
770
771        public static Pattern peInOut()
772        {
773                Pattern p = new Pattern(EntityReference.class, "changed ER");
774                p.add(erToPE(), "changed ER", "input simple PE");
775                p.add(linkToComplex(), "input simple PE", "input PE");
776                p.add(new ParticipatesInConv(RelType.INPUT), "input PE", "Conversion");
777                p.add(new ConversionSide(ConversionSide.Type.OTHER_SIDE), "input PE", "Conversion", "output PE");
778                p.add(equal(false), "input PE", "output PE");
779                p.add(linkToSpecific(), "output PE", "output simple PE");
780                p.add(peToER(), "output simple PE", "changed ER");
781                return p;
782        }
783
784        /**
785         * Pattern for an EntityReference has distinct PhysicalEntities associated with both left and
786         * right of a Conversion.
787         * @return the pattern
788         */
789        public static Pattern modifiedPESimple()
790        {
791                Pattern p = new Pattern(EntityReference.class, "modified ER");
792                p.add(erToPE(), "modified ER", "first PE");
793                p.add(participatesInConv(), "first PE", "Conversion");
794                p.add(new ConversionSide(ConversionSide.Type.OTHER_SIDE), "first PE", "Conversion", "second PE");
795                p.add(equal(false), "first PE", "second PE");
796                p.add(peToER(), "second PE", "modified ER");
797                return p;
798        }
799
800        /**
801         * Pattern for the activity of an EntityReference is changed through a Conversion.
802         * @param activating desired change
803         * @param activityFeat modification features associated with activity
804         * @param inactivityFeat modification features associated with inactivity
805         * @return the pattern
806         */
807        public static Pattern actChange(boolean activating,
808                Map<EntityReference, Set<ModificationFeature>> activityFeat,
809                Map<EntityReference, Set<ModificationFeature>> inactivityFeat)
810        {
811                Pattern p = peInOut();
812                p.add(new OR(
813                        new MappedConst(differentialActivity(activating), 0, 1),
814                        new MappedConst(new ActivityModificationChangeConstraint(
815                                activating, activityFeat, inactivityFeat), 0, 1)),
816                        "input simple PE", "output simple PE");
817                return p;
818        }
819
820        /**
821         * Pattern for finding Conversions that an EntityReference is participating.
822         * @return the pattern
823         */
824        public static Pattern modifierConv()
825        {
826                Pattern p = new Pattern(EntityReference.class, "ER");
827                p.add(erToPE(), "ER", "SPE");
828                p.add(linkToComplex(), "SPE", "PE");
829                p.add(participatesInConv(), "PE", "Conversion");
830                return p;
831        }
832
833        /**
834         * Pattern for detecting PhysicalEntity that controls a Conversion whose participants are not
835         * associated with the EntityReference of the initial PhysicalEntity.
836         * @return the pattern
837         */
838        public static Pattern hasNonSelfEffect()
839        {
840                Pattern p = new Pattern(PhysicalEntity.class, "SPE");
841                p.add(peToER(), "SPE", "ER");
842                p.add(linkToComplex(), "SPE", "PE");
843                p.add(peToControl(), "PE", "Control");
844                p.add(controlToInter(), "Control", "Inter");
845                p.add(new NOT(participantER()), "Inter", "ER");
846                return p;
847        }
848
849        // Patterns for PSB
850
851        /**
852         * Finds two Protein that appear together in a Complex.
853         * @return the pattern
854         */
855        public static Pattern bindsTo()
856        {
857                Pattern p = new Pattern(ProteinReference.class, "first PR");
858                p.add(erToPE(), "first PR", "first simple PE");
859                p.add(linkToComplex(), "first simple PE", "Complex");
860                p.add(new Type(Complex.class), "Complex");
861                p.add(linkToSpecific(), "Complex", "second simple PE");
862                p.add(peToER(), "second simple PE", "second PR");
863                p.add(equal(false), "first PR", "second PR");
864                return p;
865        }
866
867}