001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.structure.contact;
022
023import org.biojava.nbio.structure.Atom;
024import org.biojava.nbio.structure.Group;
025import org.biojava.nbio.structure.ResidueNumber;
026
027import java.io.Serializable;
028import java.util.HashMap;
029import java.util.Iterator;
030
031/**
032 * A set of residue-residue contacts.
033 * Relies on residue indices (based on SEQRES and starting with 1) to store the pairs
034 * and thus to match contacts.
035 *
036 * @author duarte_j
037 * @see ResidueIdentifier
038 */
039public class GroupContactSet implements Serializable, Iterable<GroupContact>{
040
041        private static final long serialVersionUID = 1L;
042
043        private HashMap<Pair<ResidueIdentifier>, GroupContact> contacts;
044
045        public GroupContactSet() {
046                contacts = new HashMap<Pair<ResidueIdentifier>, GroupContact>();
047        }
048
049        /**
050         * Constructs a <code>GroupContactSet</code> by collapsing the given <code>AtomContactSet</code> into
051         * residue-residue (group-group) contacts.
052         * @param atomContacts
053         */
054        public GroupContactSet(AtomContactSet atomContacts) {
055                contacts = new HashMap<Pair<ResidueIdentifier>, GroupContact>();
056                atoms2groups(atomContacts);
057        }
058
059        private void atoms2groups(AtomContactSet atomContacts) {
060
061
062                for (AtomContact atomContact:atomContacts) {
063
064                        Pair<Atom> atomPair = atomContact.getPair();
065
066                        Group iResidue = atomPair.getFirst().getGroup();
067                        Group jResidue = atomPair.getSecond().getGroup();
068
069                        // we skip the self-residue contacts
070                        if (iResidue.equals(jResidue)) continue;
071
072                        Pair<Group> residuePair = new Pair<Group> (iResidue, jResidue);
073                        Pair<ResidueIdentifier> pair = new Pair<ResidueIdentifier>(new ResidueIdentifier(iResidue), new ResidueIdentifier(jResidue));
074
075                        if (!contacts.containsKey(pair)) {
076
077                                GroupContact groupContact = new GroupContact();
078                                groupContact.setPair(residuePair);
079                                groupContact.addAtomContact(atomContact);
080
081                                contacts.put(pair, groupContact);
082
083                        } else {
084
085                                GroupContact groupContact = contacts.get(pair);
086
087                                groupContact.addAtomContact(atomContact);
088
089                        }
090
091                }
092        }
093
094        public void add(GroupContact groupContact) {
095                contacts.put(getResIdPairFromContact(groupContact),groupContact);
096        }
097
098        /**
099         * Tell whether the given group pair is a contact in this GroupContactSet,
100         * the comparison is done by matching residue numbers and chain identifiers
101         * @param group1
102         * @param group2
103         * @return
104         */
105        public boolean hasContact(Group group1, Group group2) {
106                return hasContact(group1.getResidueNumber(),group2.getResidueNumber());
107        }
108
109        /**
110         * Tell whether the given pair is a contact in this GroupContactSet,
111         * the comparison is done by matching residue numbers and chain identifiers
112         * @param resNumber1
113         * @param resNumber2
114         * @return
115         */
116        public boolean hasContact(ResidueNumber resNumber1, ResidueNumber resNumber2) {
117                return contacts.containsKey(new Pair<ResidueNumber>(resNumber1, resNumber2));
118        }
119
120        /**
121         * Tell whether the given pair is a contact in this GroupContactSet,
122         * in a chain-identifier independent way: contacts happening between different copies of
123         * the same Compound(Entity) will be considered equal as long as they have the same
124         * residue numbers.
125         * @param resId1
126         * @param resId2
127         * @return
128         */
129        public boolean hasContact(ResidueIdentifier resId1, ResidueIdentifier resId2) {
130
131                return contacts.containsKey(new Pair<ResidueIdentifier>(resId1, resId2));
132        }
133
134        /**
135         * Returns the corresponding GroupContact or null if no contact exists between the 2 given groups
136         * @param group1
137         * @param group2
138         * @return
139         */
140        public GroupContact getContact(Group group1, Group group2) {
141                return contacts.get(
142                                new Pair<ResidueNumber>(group1.getResidueNumber(),group2.getResidueNumber()));
143        }
144
145        public int size() {
146                return contacts.size();
147        }
148
149        @Override
150        public Iterator<GroupContact> iterator() {
151                return contacts.values().iterator();
152        }
153
154        private Pair<ResidueIdentifier> getResIdPairFromContact(GroupContact groupContact) {
155                return new Pair<ResidueIdentifier>(
156                                new ResidueIdentifier(groupContact.getPair().getFirst()),
157                                new ResidueIdentifier(groupContact.getPair().getSecond()) );
158
159        }
160}