2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.structure;
23 import jalview.datamodel.AlignmentAnnotation;
24 import jalview.datamodel.Mapping;
25 import jalview.datamodel.SequenceI;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.List;
31 public class StructureMapping
33 public static final int UNASSIGNED_VALUE = Integer.MIN_VALUE;
35 private static final int PDB_RES_NUM_INDEX = 0;
37 private static final int PDB_ATOM_NUM_INDEX = 1;
39 String mappingDetails;
49 // Mapping key is residue index while value is an array containing PDB resNum,
51 HashMap<Integer, int[]> mapping;
53 jalview.datamodel.Mapping seqToPdbMapping = null;
63 * a map from sequence to two values, { resNo, atomNo } in the
65 * @param mappingDetails
67 public StructureMapping(SequenceI seq, String pdbfile, String pdbid,
68 String chain, HashMap<Integer, int[]> mapping,
69 String mappingDetails)
72 this.pdbfile = pdbfile;
74 this.pdbchain = chain;
75 this.mapping = mapping;
76 this.mappingDetails = mappingDetails;
79 public StructureMapping(SequenceI seq, String pdbFile2, String pdbId2,
80 String chain, HashMap<Integer, int[]> mapping2,
81 String mappingOutput, Mapping seqToPdbMapping)
83 this(seq, pdbFile2, pdbId2, chain, mapping2, mappingOutput);
84 this.seqToPdbMapping = seqToPdbMapping;
87 public SequenceI getSequence()
92 public String getChain()
97 public String getPdbId()
105 * @return 0 or corresponding atom number for the sequence position
107 public int getAtomNum(int seqpos)
109 int[] resNumAtomMap = mapping.get(seqpos);
110 if (resNumAtomMap != null)
112 return resNumAtomMap[PDB_ATOM_NUM_INDEX];
116 return UNASSIGNED_VALUE;
123 * @return UNASSIGNED_VALUE or the corresponding residue number for the
126 public int getPDBResNum(int seqpos)
128 int[] resNumAtomMap = mapping.get(seqpos);
129 if (resNumAtomMap != null)
131 return resNumAtomMap[PDB_RES_NUM_INDEX];
135 return UNASSIGNED_VALUE;
140 * Returns a (possibly empty) list of [start, end] residue positions in the
141 * mapped structure, corresponding to the given range of sequence positions
147 public List<int[]> getPDBResNumRanges(int fromSeqPos, int toSeqPos)
149 List<int[]> result = new ArrayList<>();
153 for (int i = fromSeqPos; i <= toSeqPos; i++)
155 int resNo = getPDBResNum(i);
156 if (resNo == UNASSIGNED_VALUE)
158 continue; // no mapping from this sequence position
165 if (resNo >= startRes && resNo <= endRes)
167 // within the current range - no change
170 if (resNo == startRes - 1)
172 // extend beginning of current range
176 if (resNo == endRes + 1)
178 // extend end of current range
184 * resNo is not within or contiguous with last range,
185 * so write out the last range
187 result.add(new int[] { startRes, endRes });
193 * and add the last range
197 result.add(new int[] { startRes, endRes });
206 * @return -1 or the corresponding sequence position for a pdb residue number
208 public int getSeqPos(int pdbResNum)
210 for (Integer seqPos : mapping.keySet())
212 if (pdbResNum == getPDBResNum(seqPos))
217 return UNASSIGNED_VALUE;
221 * transfer a copy of an alignment annotation row in the PDB chain coordinate
222 * system onto the mapped sequence
225 * @return the copy that was remapped to the mapped sequence
226 * @note this method will create a copy and add it to the dataset sequence for
227 * the mapped sequence as well as the mapped sequence (if it is not a
230 public AlignmentAnnotation transfer(AlignmentAnnotation ana)
232 AlignmentAnnotation ala_copy = new AlignmentAnnotation(ana);
233 SequenceI ds = sequence;
234 while (ds.getDatasetSequence() != null)
236 ds = ds.getDatasetSequence();
238 // need to relocate annotation from pdb coordinates to local sequence
239 // -1,-1 doesn't look at pdbresnum but fails to remap sequence positions...
241 ala_copy.remap(ds, mapping, -1, -1, 0);
242 ds.addAlignmentAnnotation(ala_copy);
245 // mapping wasn't to an original dataset sequence, so we make a copy on
246 // the mapped sequence too
247 ala_copy = new AlignmentAnnotation(ala_copy);
248 sequence.addAlignmentAnnotation(ala_copy);
253 public String getMappingDetailsOutput()
255 return mappingDetails;
258 public HashMap<Integer, int[]> getMapping()
263 public Mapping getSeqToPdbMapping()
265 return seqToPdbMapping;
269 * A hash function that satisfies the contract that if two mappings are
270 * equal(), they have the same hashCode
273 public int hashCode()
275 final int prime = 31;
277 result = prime * result
278 + ((mappingDetails == null) ? 0 : mappingDetails.hashCode());
279 result = prime * result
280 + ((pdbchain == null) ? 0 : pdbchain.hashCode());
281 result = prime * result + ((pdbfile == null) ? 0 : pdbfile.hashCode());
282 result = prime * result + ((pdbid == null) ? 0 : pdbid.hashCode());
283 result = prime * result
284 + ((seqToPdbMapping == null) ? 0 : seqToPdbMapping.hashCode());
285 result = prime * result
286 + ((sequence == null) ? 0 : sequence.hashCode());
291 public boolean equals(Object obj)
301 if (getClass() != obj.getClass())
305 StructureMapping other = (StructureMapping) obj;
306 if (mappingDetails == null)
308 if (other.mappingDetails != null)
313 else if (!mappingDetails.equals(other.mappingDetails))
317 if (pdbchain == null)
319 if (other.pdbchain != null)
324 else if (!pdbchain.equals(other.pdbchain))
330 if (other.pdbfile != null)
335 else if (!pdbfile.equals(other.pdbfile))
341 if (other.pdbid != null)
346 else if (!pdbid.equals(other.pdbid))
350 if (seqToPdbMapping == null)
352 if (other.seqToPdbMapping != null)
357 else if (!seqToPdbMapping.equals(other.seqToPdbMapping))
361 if (sequence != other.sequence)