1 package jalview.structures.models;
3 import jalview.api.StructureSelectionManagerProvider;
4 import jalview.datamodel.PDBEntry;
5 import jalview.datamodel.SequenceI;
6 import jalview.structure.StructureListener;
7 import jalview.structure.StructureSelectionManager;
8 import jalview.util.MessageManager;
10 import java.awt.event.ComponentEvent;
11 import java.util.ArrayList;
12 import java.util.List;
15 * A base class to hold common function for protein structure model binding.
16 * Initial version created by refactoring JMol and Chimera binding models, but
17 * other structure viewers could in principle be accommodated in future.
22 public abstract class AAStructureBindingModel extends
23 SequenceStructureBindingModel implements StructureListener,
24 StructureSelectionManagerProvider
27 private StructureSelectionManager ssm;
29 private PDBEntry[] pdbEntry;
32 * sequences mapped to each pdbentry
34 private SequenceI[][] sequence;
37 * array of target chains for sequences - tied to pdbentry and sequence[]
39 private String[][] chains;
42 * datasource protocol for access to PDBEntrylatest
44 String protocol = null;
46 protected boolean colourBySequence = true;
54 public AAStructureBindingModel(StructureSelectionManager ssm,
70 public AAStructureBindingModel(StructureSelectionManager ssm,
71 PDBEntry[] pdbentry, SequenceI[][] sequenceIs, String[][] chains,
75 this.sequence = sequenceIs;
77 this.pdbEntry = pdbentry;
78 this.protocol = protocol;
81 this.chains = new String[pdbentry.length][];
85 public StructureSelectionManager getSsm()
91 * Returns the i'th PDBEntry (or null)
96 public PDBEntry getPdbEntry(int i)
98 return (pdbEntry != null && pdbEntry.length > i) ? pdbEntry[i] : null;
102 * Returns the number of modelled PDB file entries.
106 public int getPdbCount()
108 return pdbEntry == null ? 0 : pdbEntry.length;
111 public SequenceI[][] getSequence()
116 public String[][] getChains()
121 public String getProtocol()
126 // TODO may remove this if calling methods can be pulled up here
127 protected void setPdbentry(PDBEntry[] pdbentry)
129 this.pdbEntry = pdbentry;
132 protected void setSequence(SequenceI[][] sequence)
134 this.sequence = sequence;
137 protected void setChains(String[][] chains)
139 this.chains = chains;
143 * Construct a title string for the viewer window based on the data Jalview
145 * @param viewerName TODO
150 public String getViewerTitle(String viewerName, boolean verbose)
152 if (getSequence() == null || getSequence().length < 1
154 || getSequence()[0].length < 1)
156 return ("Jalview " + viewerName + " Window");
158 // TODO: give a more informative title when multiple structures are
160 StringBuilder title = new StringBuilder(64);
161 final PDBEntry pdbEntry = getPdbEntry(0);
162 title.append(viewerName + " view for " + getSequence()[0][0].getName()
168 if (pdbEntry.getProperty() != null)
170 if (pdbEntry.getProperty().get("method") != null)
172 title.append(" Method: ");
173 title.append(pdbEntry.getProperty().get("method"));
175 if (pdbEntry.getProperty().get("chains") != null)
177 title.append(" Chain:");
178 title.append(pdbEntry.getProperty().get("chains"));
182 return title.toString();
186 * Called by after closeViewer is called, to release any resources and
187 * references so they can be garbage collected. Override if needed.
189 protected void releaseUIResources()
194 public boolean isColourBySequence()
196 return colourBySequence;
199 public void setColourBySequence(boolean colourBySequence)
201 this.colourBySequence = colourBySequence;
204 protected void addSequenceAndChain(int pe, SequenceI[] seq,
207 if (pe < 0 || pe >= getPdbCount())
209 throw new Error(MessageManager.formatMessage(
210 "error.implementation_error_no_pdbentry_from_index",
212 { Integer.valueOf(pe).toString() }));
214 final String nullChain = "TheNullChain";
215 List<SequenceI> s = new ArrayList<SequenceI>();
216 List<String> c = new ArrayList<String>();
217 if (getChains() == null)
219 setChains(new String[getPdbCount()][]);
221 if (getSequence()[pe] != null)
223 for (int i = 0; i < getSequence()[pe].length; i++)
225 s.add(getSequence()[pe][i]);
226 if (getChains()[pe] != null)
228 if (i < getChains()[pe].length)
230 c.add(getChains()[pe][i]);
239 if (tchain != null && tchain.length > 0)
246 for (int i = 0; i < seq.length; i++)
248 if (!s.contains(seq[i]))
251 if (tchain != null && i < tchain.length)
253 c.add(tchain[i] == null ? nullChain : tchain[i]);
257 SequenceI[] tmp = s.toArray(new SequenceI[s.size()]);
258 getSequence()[pe] = tmp;
261 String[] tch = c.toArray(new String[c.size()]);
262 for (int i = 0; i < tch.length; i++)
264 if (tch[i] == nullChain)
269 getChains()[pe] = tch;
273 getChains()[pe] = null;
278 * add structures and any known sequence associations
280 * @returns the pdb entries added to the current set.
282 public synchronized PDBEntry[] addSequenceAndChain(PDBEntry[] pdbe, SequenceI[][] seq,
285 List<PDBEntry> v = new ArrayList<PDBEntry>();
286 List<int[]> rtn = new ArrayList<int[]>();
287 for (int i = 0; i < getPdbCount(); i++)
289 v.add(getPdbEntry(i));
291 for (int i = 0; i < pdbe.length; i++)
293 int r = v.indexOf(pdbe[i]);
294 if (r == -1 || r >= getPdbCount())
302 // just make sure the sequence/chain entries are all up to date
303 addSequenceAndChain(r, seq[i], chns[i]);
306 pdbe = v.toArray(new PDBEntry[v.size()]);
310 // expand the tied sequence[] and string[] arrays
311 SequenceI[][] sqs = new SequenceI[getPdbCount()][];
312 String[][] sch = new String[getPdbCount()][];
313 System.arraycopy(getSequence(), 0, sqs, 0, getSequence().length);
314 System.arraycopy(getChains(), 0, sch, 0, this.getChains().length);
317 pdbe = new PDBEntry[rtn.size()];
318 for (int r = 0; r < pdbe.length; r++)
320 int[] stri = (rtn.get(r));
321 // record the pdb file as a new addition
322 pdbe[r] = getPdbEntry(stri[0]);
323 // and add the new sequence/chain entries
324 addSequenceAndChain(stri[0], seq[stri[1]], chns[stri[1]]);
335 * Add sequences to the pe'th pdbentry's sequence set.
340 public void addSequence(int pe, SequenceI[] seq)
342 addSequenceAndChain(pe, seq, null);