1 package jalview.structures.models;
3 import java.util.ArrayList;
6 import jalview.api.StructureSelectionManagerProvider;
7 import jalview.datamodel.PDBEntry;
8 import jalview.datamodel.SequenceI;
9 import jalview.structure.AtomSpec;
10 import jalview.structure.StructureListener;
11 import jalview.structure.StructureSelectionManager;
12 import jalview.util.Comparison;
13 import jalview.util.MessageManager;
17 * A base class to hold common function for protein structure model binding.
18 * Initial version created by refactoring JMol and Chimera binding models, but
19 * other structure viewers could in principle be accommodated in future.
24 public abstract class AAStructureBindingModel extends
25 SequenceStructureBindingModel implements StructureListener,
26 StructureSelectionManagerProvider
29 private StructureSelectionManager ssm;
31 private PDBEntry[] pdbEntry;
34 * sequences mapped to each pdbentry
36 private SequenceI[][] sequence;
39 * array of target chains for sequences - tied to pdbentry and sequence[]
41 private String[][] chains;
44 * datasource protocol for access to PDBEntrylatest
46 String protocol = null;
48 protected boolean colourBySequence = true;
50 private boolean nucleotide;
58 public AAStructureBindingModel(StructureSelectionManager ssm,
74 public AAStructureBindingModel(StructureSelectionManager ssm,
75 PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
79 this.sequence = sequenceIs;
80 this.nucleotide = Comparison.isNucleotide(sequenceIs);
82 this.pdbEntry = pdbentry;
83 this.protocol = protocol;
86 this.chains = new String[pdbentry.length][];
90 public StructureSelectionManager getSsm()
96 * Returns the i'th PDBEntry (or null)
101 public PDBEntry getPdbEntry(int i)
103 return (pdbEntry != null && pdbEntry.length > i) ? pdbEntry[i] : null;
107 * Answers true if this binding includes the given PDB id, else false
112 public boolean hasPdbId(String pdbId)
114 if (pdbEntry != null)
116 for (PDBEntry pdb : pdbEntry)
118 if (pdb.getId().equals(pdbId))
128 * Returns the number of modelled PDB file entries.
132 public int getPdbCount()
134 return pdbEntry == null ? 0 : pdbEntry.length;
137 public SequenceI[][] getSequence()
142 public String[][] getChains()
147 public String getProtocol()
152 // TODO may remove this if calling methods can be pulled up here
153 protected void setPdbentry(PDBEntry[] pdbentry)
155 this.pdbEntry = pdbentry;
158 protected void setSequence(SequenceI[][] sequence)
160 this.sequence = sequence;
163 protected void setChains(String[][] chains)
165 this.chains = chains;
169 * Construct a title string for the viewer window based on the data Jalview
171 * @param viewerName TODO
176 public String getViewerTitle(String viewerName, boolean verbose)
178 if (getSequence() == null || getSequence().length < 1
180 || getSequence()[0].length < 1)
182 return ("Jalview " + viewerName + " Window");
184 // TODO: give a more informative title when multiple structures are
186 StringBuilder title = new StringBuilder(64);
187 final PDBEntry pdbEntry = getPdbEntry(0);
188 title.append(viewerName + " view for " + getSequence()[0][0].getName()
194 if (pdbEntry.getProperty() != null)
196 if (pdbEntry.getProperty().get("method") != null)
198 title.append(" Method: ");
199 title.append(pdbEntry.getProperty().get("method"));
201 if (pdbEntry.getProperty().get("chains") != null)
203 title.append(" Chain:");
204 title.append(pdbEntry.getProperty().get("chains"));
208 return title.toString();
212 * Called by after closeViewer is called, to release any resources and
213 * references so they can be garbage collected. Override if needed.
215 protected void releaseUIResources()
220 public boolean isColourBySequence()
222 return colourBySequence;
225 public void setColourBySequence(boolean colourBySequence)
227 this.colourBySequence = colourBySequence;
230 protected void addSequenceAndChain(int pe, SequenceI[] seq,
233 if (pe < 0 || pe >= getPdbCount())
235 throw new Error(MessageManager.formatMessage(
236 "error.implementation_error_no_pdbentry_from_index",
238 { Integer.valueOf(pe).toString() }));
240 final String nullChain = "TheNullChain";
241 List<SequenceI> s = new ArrayList<SequenceI>();
242 List<String> c = new ArrayList<String>();
243 if (getChains() == null)
245 setChains(new String[getPdbCount()][]);
247 if (getSequence()[pe] != null)
249 for (int i = 0; i < getSequence()[pe].length; i++)
251 s.add(getSequence()[pe][i]);
252 if (getChains()[pe] != null)
254 if (i < getChains()[pe].length)
256 c.add(getChains()[pe][i]);
265 if (tchain != null && tchain.length > 0)
272 for (int i = 0; i < seq.length; i++)
274 if (!s.contains(seq[i]))
277 if (tchain != null && i < tchain.length)
279 c.add(tchain[i] == null ? nullChain : tchain[i]);
283 SequenceI[] tmp = s.toArray(new SequenceI[s.size()]);
284 getSequence()[pe] = tmp;
287 String[] tch = c.toArray(new String[c.size()]);
288 for (int i = 0; i < tch.length; i++)
290 if (tch[i] == nullChain)
295 getChains()[pe] = tch;
299 getChains()[pe] = null;
304 * add structures and any known sequence associations
306 * @returns the pdb entries added to the current set.
308 public synchronized PDBEntry[] addSequenceAndChain(PDBEntry[] pdbe, SequenceI[][] seq,
311 List<PDBEntry> v = new ArrayList<PDBEntry>();
312 List<int[]> rtn = new ArrayList<int[]>();
313 for (int i = 0; i < getPdbCount(); i++)
315 v.add(getPdbEntry(i));
317 for (int i = 0; i < pdbe.length; i++)
319 int r = v.indexOf(pdbe[i]);
320 if (r == -1 || r >= getPdbCount())
328 // just make sure the sequence/chain entries are all up to date
329 addSequenceAndChain(r, seq[i], chns[i]);
332 pdbe = v.toArray(new PDBEntry[v.size()]);
336 // expand the tied sequence[] and string[] arrays
337 SequenceI[][] sqs = new SequenceI[getPdbCount()][];
338 String[][] sch = new String[getPdbCount()][];
339 System.arraycopy(getSequence(), 0, sqs, 0, getSequence().length);
340 System.arraycopy(getChains(), 0, sch, 0, this.getChains().length);
343 pdbe = new PDBEntry[rtn.size()];
344 for (int r = 0; r < pdbe.length; r++)
346 int[] stri = (rtn.get(r));
347 // record the pdb file as a new addition
348 pdbe[r] = getPdbEntry(stri[0]);
349 // and add the new sequence/chain entries
350 addSequenceAndChain(stri[0], seq[stri[1]], chns[stri[1]]);
361 * Add sequences to the pe'th pdbentry's sequence set.
366 public void addSequence(int pe, SequenceI[] seq)
368 addSequenceAndChain(pe, seq, null);
372 * add the given sequences to the mapping scope for the given pdb file handle
375 * - pdbFile identifier
377 * - set of sequences it can be mapped to
379 public void addSequenceForStructFile(String pdbFile, SequenceI[] seq)
381 for (int pe = 0; pe < getPdbCount(); pe++)
383 if (getPdbEntry(pe).getFile().equals(pdbFile))
385 addSequence(pe, seq);
391 public void highlightAtoms(List<AtomSpec> atoms)
395 for (AtomSpec atom : atoms)
397 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
398 atom.getChain(), atom.getPdbFile());
403 protected abstract void highlightAtom(int atomIndex, int pdbResNum,
404 String chain, String pdbFile);
406 protected boolean isNucleotide()
408 return this.nucleotide;