1 package jalview.structures.models;
3 import java.util.ArrayList;
4 import java.util.Arrays;
7 import jalview.api.StructureSelectionManagerProvider;
8 import jalview.datamodel.PDBEntry;
9 import jalview.datamodel.SequenceI;
10 import jalview.structure.AtomSpec;
11 import jalview.structure.StructureListener;
12 import jalview.structure.StructureSelectionManager;
13 import jalview.util.Comparison;
14 import jalview.util.MessageManager;
18 * A base class to hold common function for protein structure model binding.
19 * Initial version created by refactoring JMol and Chimera binding models, but
20 * other structure viewers could in principle be accommodated in future.
25 public abstract class AAStructureBindingModel extends
26 SequenceStructureBindingModel implements StructureListener,
27 StructureSelectionManagerProvider
30 private StructureSelectionManager ssm;
32 private PDBEntry[] pdbEntry;
35 * sequences mapped to each pdbentry
37 private SequenceI[][] sequence;
40 * array of target chains for sequences - tied to pdbentry and sequence[]
42 private String[][] chains;
45 * datasource protocol for access to PDBEntrylatest
47 String protocol = null;
49 protected boolean colourBySequence = true;
51 private boolean nucleotide;
59 public AAStructureBindingModel(StructureSelectionManager ssm,
75 public AAStructureBindingModel(StructureSelectionManager ssm,
76 PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
80 this.sequence = sequenceIs;
81 this.nucleotide = Comparison.isNucleotide(sequenceIs);
83 this.pdbEntry = pdbentry;
84 this.protocol = protocol;
87 this.chains = new String[pdbentry.length][];
91 public StructureSelectionManager getSsm()
97 * Returns the i'th PDBEntry (or null)
102 public PDBEntry getPdbEntry(int i)
104 return (pdbEntry != null && pdbEntry.length > i) ? pdbEntry[i] : null;
108 * Answers true if this binding includes the given PDB id, else false
113 public boolean hasPdbId(String pdbId)
115 if (pdbEntry != null)
117 for (PDBEntry pdb : pdbEntry)
119 if (pdb.getId().equals(pdbId))
129 * Returns the number of modelled PDB file entries.
133 public int getPdbCount()
135 return pdbEntry == null ? 0 : pdbEntry.length;
138 public SequenceI[][] getSequence()
143 public String[][] getChains()
148 public String getProtocol()
153 // TODO may remove this if calling methods can be pulled up here
154 protected void setPdbentry(PDBEntry[] pdbentry)
156 this.pdbEntry = pdbentry;
159 protected void setSequence(SequenceI[][] sequence)
161 this.sequence = sequence;
164 protected void setChains(String[][] chains)
166 this.chains = chains;
170 * Construct a title string for the viewer window based on the data Jalview
172 * @param viewerName TODO
177 public String getViewerTitle(String viewerName, boolean verbose)
179 if (getSequence() == null || getSequence().length < 1
181 || getSequence()[0].length < 1)
183 return ("Jalview " + viewerName + " Window");
185 // TODO: give a more informative title when multiple structures are
187 StringBuilder title = new StringBuilder(64);
188 final PDBEntry pdbEntry = getPdbEntry(0);
189 title.append(viewerName + " view for " + getSequence()[0][0].getName()
195 if (pdbEntry.getProperty() != null)
197 if (pdbEntry.getProperty().get("method") != null)
199 title.append(" Method: ");
200 title.append(pdbEntry.getProperty().get("method"));
202 if (pdbEntry.getProperty().get("chains") != null)
204 title.append(" Chain:");
205 title.append(pdbEntry.getProperty().get("chains"));
209 return title.toString();
213 * Called by after closeViewer is called, to release any resources and
214 * references so they can be garbage collected. Override if needed.
216 protected void releaseUIResources()
221 public boolean isColourBySequence()
223 return colourBySequence;
226 public void setColourBySequence(boolean colourBySequence)
228 this.colourBySequence = colourBySequence;
231 protected void addSequenceAndChain(int pe, SequenceI[] seq,
234 if (pe < 0 || pe >= getPdbCount())
236 throw new Error(MessageManager.formatMessage(
237 "error.implementation_error_no_pdbentry_from_index",
239 { Integer.valueOf(pe).toString() }));
241 final String nullChain = "TheNullChain";
242 List<SequenceI> s = new ArrayList<SequenceI>();
243 List<String> c = new ArrayList<String>();
244 if (getChains() == null)
246 setChains(new String[getPdbCount()][]);
248 if (getSequence()[pe] != null)
250 for (int i = 0; i < getSequence()[pe].length; i++)
252 s.add(getSequence()[pe][i]);
253 if (getChains()[pe] != null)
255 if (i < getChains()[pe].length)
257 c.add(getChains()[pe][i]);
266 if (tchain != null && tchain.length > 0)
273 for (int i = 0; i < seq.length; i++)
275 if (!s.contains(seq[i]))
278 if (tchain != null && i < tchain.length)
280 c.add(tchain[i] == null ? nullChain : tchain[i]);
284 SequenceI[] tmp = s.toArray(new SequenceI[s.size()]);
285 getSequence()[pe] = tmp;
288 String[] tch = c.toArray(new String[c.size()]);
289 for (int i = 0; i < tch.length; i++)
291 if (tch[i] == nullChain)
296 getChains()[pe] = tch;
300 getChains()[pe] = null;
305 * add structures and any known sequence associations
307 * @returns the pdb entries added to the current set.
309 public synchronized PDBEntry[] addSequenceAndChain(PDBEntry[] pdbe, SequenceI[][] seq,
312 List<PDBEntry> v = new ArrayList<PDBEntry>();
313 List<int[]> rtn = new ArrayList<int[]>();
314 for (int i = 0; i < getPdbCount(); i++)
316 v.add(getPdbEntry(i));
318 for (int i = 0; i < pdbe.length; i++)
320 int r = v.indexOf(pdbe[i]);
321 if (r == -1 || r >= getPdbCount())
329 // just make sure the sequence/chain entries are all up to date
330 addSequenceAndChain(r, seq[i], chns[i]);
333 pdbe = v.toArray(new PDBEntry[v.size()]);
337 // expand the tied sequence[] and string[] arrays
338 SequenceI[][] sqs = new SequenceI[getPdbCount()][];
339 String[][] sch = new String[getPdbCount()][];
340 System.arraycopy(getSequence(), 0, sqs, 0, getSequence().length);
341 System.arraycopy(getChains(), 0, sch, 0, this.getChains().length);
344 pdbe = new PDBEntry[rtn.size()];
345 for (int r = 0; r < pdbe.length; r++)
347 int[] stri = (rtn.get(r));
348 // record the pdb file as a new addition
349 pdbe[r] = getPdbEntry(stri[0]);
350 // and add the new sequence/chain entries
351 addSequenceAndChain(stri[0], seq[stri[1]], chns[stri[1]]);
362 * Add sequences to the pe'th pdbentry's sequence set.
367 public void addSequence(int pe, SequenceI[] seq)
369 addSequenceAndChain(pe, seq, null);
373 * add the given sequences to the mapping scope for the given pdb file handle
376 * - pdbFile identifier
378 * - set of sequences it can be mapped to
380 public void addSequenceForStructFile(String pdbFile, SequenceI[] seq)
382 for (int pe = 0; pe < getPdbCount(); pe++)
384 if (getPdbEntry(pe).getFile().equals(pdbFile))
386 addSequence(pe, seq);
392 * Returns a readable description of all mappings for the wrapped pdbfile to
393 * any mapped sequences
399 public String printMappings()
401 if (pdbEntry == null)
405 StringBuilder sb = new StringBuilder(128);
406 for (int pdbe = 0; pdbe < getPdbCount(); pdbe++)
408 String pdbfile = getPdbEntry(pdbe).getFile();
409 List<SequenceI> seqs = Arrays.asList(getSequence()[pdbe]);
410 sb.append(getSsm().printMappings(pdbfile, seqs));
412 return sb.toString();
416 public void highlightAtoms(List<AtomSpec> atoms)
420 for (AtomSpec atom : atoms)
422 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
423 atom.getChain(), atom.getPdbFile());
428 protected abstract void highlightAtom(int atomIndex, int pdbResNum,
429 String chain, String pdbFile);
431 protected boolean isNucleotide()
433 return this.nucleotide;