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 * Returns the number of modelled PDB file entries.
111 public int getPdbCount()
113 return pdbEntry == null ? 0 : pdbEntry.length;
116 public SequenceI[][] getSequence()
121 public String[][] getChains()
126 public String getProtocol()
131 // TODO may remove this if calling methods can be pulled up here
132 protected void setPdbentry(PDBEntry[] pdbentry)
134 this.pdbEntry = pdbentry;
137 protected void setSequence(SequenceI[][] sequence)
139 this.sequence = sequence;
142 protected void setChains(String[][] chains)
144 this.chains = chains;
148 * Construct a title string for the viewer window based on the data Jalview
150 * @param viewerName TODO
155 public String getViewerTitle(String viewerName, boolean verbose)
157 if (getSequence() == null || getSequence().length < 1
159 || getSequence()[0].length < 1)
161 return ("Jalview " + viewerName + " Window");
163 // TODO: give a more informative title when multiple structures are
165 StringBuilder title = new StringBuilder(64);
166 final PDBEntry pdbEntry = getPdbEntry(0);
167 title.append(viewerName + " view for " + getSequence()[0][0].getName()
173 if (pdbEntry.getProperty() != null)
175 if (pdbEntry.getProperty().get("method") != null)
177 title.append(" Method: ");
178 title.append(pdbEntry.getProperty().get("method"));
180 if (pdbEntry.getProperty().get("chains") != null)
182 title.append(" Chain:");
183 title.append(pdbEntry.getProperty().get("chains"));
187 return title.toString();
191 * Called by after closeViewer is called, to release any resources and
192 * references so they can be garbage collected. Override if needed.
194 protected void releaseUIResources()
199 public boolean isColourBySequence()
201 return colourBySequence;
204 public void setColourBySequence(boolean colourBySequence)
206 this.colourBySequence = colourBySequence;
209 protected void addSequenceAndChain(int pe, SequenceI[] seq,
212 if (pe < 0 || pe >= getPdbCount())
214 throw new Error(MessageManager.formatMessage(
215 "error.implementation_error_no_pdbentry_from_index",
217 { Integer.valueOf(pe).toString() }));
219 final String nullChain = "TheNullChain";
220 List<SequenceI> s = new ArrayList<SequenceI>();
221 List<String> c = new ArrayList<String>();
222 if (getChains() == null)
224 setChains(new String[getPdbCount()][]);
226 if (getSequence()[pe] != null)
228 for (int i = 0; i < getSequence()[pe].length; i++)
230 s.add(getSequence()[pe][i]);
231 if (getChains()[pe] != null)
233 if (i < getChains()[pe].length)
235 c.add(getChains()[pe][i]);
244 if (tchain != null && tchain.length > 0)
251 for (int i = 0; i < seq.length; i++)
253 if (!s.contains(seq[i]))
256 if (tchain != null && i < tchain.length)
258 c.add(tchain[i] == null ? nullChain : tchain[i]);
262 SequenceI[] tmp = s.toArray(new SequenceI[s.size()]);
263 getSequence()[pe] = tmp;
266 String[] tch = c.toArray(new String[c.size()]);
267 for (int i = 0; i < tch.length; i++)
269 if (tch[i] == nullChain)
274 getChains()[pe] = tch;
278 getChains()[pe] = null;
283 * add structures and any known sequence associations
285 * @returns the pdb entries added to the current set.
287 public synchronized PDBEntry[] addSequenceAndChain(PDBEntry[] pdbe, SequenceI[][] seq,
290 List<PDBEntry> v = new ArrayList<PDBEntry>();
291 List<int[]> rtn = new ArrayList<int[]>();
292 for (int i = 0; i < getPdbCount(); i++)
294 v.add(getPdbEntry(i));
296 for (int i = 0; i < pdbe.length; i++)
298 int r = v.indexOf(pdbe[i]);
299 if (r == -1 || r >= getPdbCount())
307 // just make sure the sequence/chain entries are all up to date
308 addSequenceAndChain(r, seq[i], chns[i]);
311 pdbe = v.toArray(new PDBEntry[v.size()]);
315 // expand the tied sequence[] and string[] arrays
316 SequenceI[][] sqs = new SequenceI[getPdbCount()][];
317 String[][] sch = new String[getPdbCount()][];
318 System.arraycopy(getSequence(), 0, sqs, 0, getSequence().length);
319 System.arraycopy(getChains(), 0, sch, 0, this.getChains().length);
322 pdbe = new PDBEntry[rtn.size()];
323 for (int r = 0; r < pdbe.length; r++)
325 int[] stri = (rtn.get(r));
326 // record the pdb file as a new addition
327 pdbe[r] = getPdbEntry(stri[0]);
328 // and add the new sequence/chain entries
329 addSequenceAndChain(stri[0], seq[stri[1]], chns[stri[1]]);
340 * Add sequences to the pe'th pdbentry's sequence set.
345 public void addSequence(int pe, SequenceI[] seq)
347 addSequenceAndChain(pe, seq, null);
351 * add the given sequences to the mapping scope for the given pdb file handle
354 * - pdbFile identifier
356 * - set of sequences it can be mapped to
358 public void addSequenceForStructFile(String pdbFile, SequenceI[] seq)
360 for (int pe = 0; pe < getPdbCount(); pe++)
362 if (getPdbEntry(pe).getFile().equals(pdbFile))
364 addSequence(pe, seq);
370 public void highlightAtoms(List<AtomSpec> atoms)
374 for (AtomSpec atom : atoms)
376 highlightAtom(atom.getAtomIndex(), atom.getPdbResNum(),
377 atom.getChain(), atom.getPdbFile());
382 protected abstract void highlightAtom(int atomIndex, int pdbResNum,
383 String chain, String pdbFile);
385 protected boolean isNucleotide()
387 return this.nucleotide;