Check bounds of loaded comp
[jalview.git] / src / jalview / structure / StructureSelectionManager.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.structure;
20
21 import java.io.*;
22 import java.util.*;
23
24 import MCview.*;
25 import jalview.analysis.*;
26 import jalview.datamodel.*;
27
28 public class StructureSelectionManager
29 {
30   static StructureSelectionManager instance;
31   StructureMapping[] mappings;
32   Hashtable mappingData = new Hashtable();
33
34   public static StructureSelectionManager getStructureSelectionManager()
35   {
36     if (instance == null)
37     {
38       instance = new StructureSelectionManager();
39     }
40
41     return instance;
42   }
43
44   Vector listeners = new Vector();
45   public void addStructureViewerListener(Object svl)
46   {
47     if (!listeners.contains(svl))
48     {
49       listeners.addElement(svl);
50     }
51   }
52
53   public String alreadyMappedToFile(String pdbid)
54   {
55     if (mappings != null)
56     {
57       for (int i = 0; i < mappings.length; i++)
58       {
59         if (mappings[i].getPdbId().equals(pdbid))
60         {
61           return mappings[i].pdbfile;
62         }
63       }
64     }
65     return null;
66   }
67
68   /*
69      There will be better ways of doing this in the future, for now we'll use
70      the tried and tested MCview pdb mapping
71    */
72   synchronized public MCview.PDBfile setMapping(
73       SequenceI[] sequence,
74       String[] targetChains,
75       String pdbFile,
76       String protocol)
77   {
78     MCview.PDBfile pdb = null;
79     try
80     {
81       pdb = new MCview.PDBfile(pdbFile, protocol);
82     }
83     catch (Exception ex)
84     {
85       ex.printStackTrace();
86       return null;
87     }
88
89     String targetChain;
90     for (int s = 0; s < sequence.length; s++)
91     {
92       if(targetChains!=null && targetChains[s]!=null)
93         targetChain = targetChains[s];
94       else if (sequence[s].getName().indexOf("|") > -1)
95       {
96         targetChain = sequence[s].getName().substring(
97             sequence[s].getName().lastIndexOf("|") + 1);
98       }
99       else
100         targetChain = "";
101
102
103       int max = -10;
104       AlignSeq maxAlignseq = null;
105       String maxChainId = " ";
106       PDBChain maxChain = null;
107
108       for (int i = 0; i < pdb.chains.size(); i++)
109       {
110         AlignSeq as = new AlignSeq(sequence[s],
111                                    ( (PDBChain) pdb.chains.elementAt(i)).
112                                    sequence,
113                                    AlignSeq.PEP);
114         as.calcScoreMatrix();
115         as.traceAlignment();
116         PDBChain chain = ( (PDBChain) pdb.chains.elementAt(i));
117
118         if (as.maxscore > max
119             || (as.maxscore == max && chain.id.equals(targetChain)))
120         {
121           maxChain = chain;
122           max = as.maxscore;
123           maxAlignseq = as;
124           maxChainId = chain.id;
125         }
126       }
127
128       final StringBuffer mappingDetails = new StringBuffer();
129       mappingDetails.append("\n\nPDB Sequence is :\nSequence = " +
130                             maxChain.sequence.getSequenceAsString());
131       mappingDetails.append("\nNo of residues = " +
132                             maxChain.residues.
133                             size() +
134                             "\n\n");
135       PrintStream ps = new PrintStream(System.out)
136       {
137         public void print(String x)
138         {
139           mappingDetails.append(x);
140         }
141
142         public void println()
143         {
144           mappingDetails.append("\n");
145         }
146       };
147
148       maxAlignseq.printAlignment(ps);
149
150       mappingDetails.append("\nPDB start/end " + maxAlignseq.seq2start + " " +
151                             maxAlignseq.seq2end);
152       mappingDetails.append("\nSEQ start/end "
153                             + (maxAlignseq.seq1start + sequence[s].getStart() - 1) +
154                             " "
155                             + (maxAlignseq.seq1end + sequence[s].getEnd() - 1));
156
157       maxChain.makeExactMapping(maxAlignseq, sequence[s]);
158
159       maxChain.transferRESNUMFeatures(sequence[s], null);
160
161       int[][] mapping = new int[sequence[s].getEnd() + 2][2];
162       int resNum = -10000;
163       int index = 0;
164
165
166       do
167       {
168         Atom tmp = (Atom) maxChain.atoms.elementAt(index);
169         if (resNum != tmp.resNumber && tmp.alignmentMapping != -1)
170         {
171           resNum = tmp.resNumber;
172           mapping[tmp.alignmentMapping+1][0] = tmp.resNumber;
173           mapping[tmp.alignmentMapping+1][1] = tmp.atomIndex;
174         }
175
176         index++;
177       }
178       while(index < maxChain.atoms.size());
179
180       if (mappings == null)
181       {
182         mappings = new StructureMapping[1];
183       }
184       else
185       {
186         StructureMapping[] tmp = new StructureMapping[mappings.length + 1];
187         System.arraycopy(mappings, 0, tmp, 0, mappings.length);
188         mappings = tmp;
189       }
190
191       if(protocol.equals(jalview.io.AppletFormatAdapter.PASTE))
192         pdbFile = "INLINE"+pdb.id;
193
194       mappings[mappings.length - 1]
195           = new StructureMapping(sequence[s], pdbFile, pdb.id, maxChainId,
196                                  mapping, mappingDetails.toString());
197       maxChain.transferResidueAnnotation(mappings[mappings.length-1]);
198     }
199     /////////
200
201     return pdb;
202   }
203
204   public void removeStructureViewerListener(Object svl, String pdbfile)
205   {
206     listeners.removeElement(svl);
207
208     boolean removeMapping = true;
209
210     StructureListener sl;
211     for (int i = 0; i < listeners.size(); i++)
212     {
213       if (listeners.elementAt(i) instanceof StructureListener)
214       {
215         sl = (StructureListener) listeners.elementAt(i);
216         if (sl.getPdbFile().equals(pdbfile))
217         {
218           removeMapping = false;
219           break;
220         }
221       }
222     }
223
224     if (removeMapping && mappings!=null)
225     {
226       Vector tmp = new Vector();
227       for (int i = 0; i < mappings.length; i++)
228       {
229         if (!mappings[i].pdbfile.equals(pdbfile))
230         {
231           tmp.addElement(mappings[i]);
232         }
233       }
234
235       mappings = new StructureMapping[tmp.size()];
236       tmp.copyInto(mappings);
237     }
238   }
239
240   public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
241   {
242     SequenceListener sl;
243     for (int i = 0; i < listeners.size(); i++)
244     {
245       if (listeners.elementAt(i) instanceof SequenceListener)
246       {
247         sl = (SequenceListener) listeners.elementAt(i);
248
249         for (int j = 0; j < mappings.length; j++)
250         {
251           if (mappings[j].pdbfile.equals(pdbfile) &&
252               mappings[j].pdbchain.equals(chain))
253           {
254             sl.highlightSequence(mappings[j].sequence,
255                                  mappings[j].getSeqPos(pdbResNum));
256           }
257         }
258       }
259     }
260   }
261
262   public void mouseOverSequence(SequenceI seq, int index)
263   {
264     StructureListener sl;
265     int atomNo = 0;
266     for (int i = 0; i < listeners.size(); i++)
267     {
268       if (listeners.elementAt(i) instanceof StructureListener)
269       {
270         sl = (StructureListener) listeners.elementAt(i);
271
272         for (int j = 0; j < mappings.length; j++)
273         {
274           if (mappings[j].sequence == seq)
275           {
276             atomNo = mappings[j].getAtomNum(index);
277
278             if (atomNo > 0)
279             {
280               sl.highlightAtom(atomNo,
281                                mappings[j].getPDBResNum(index),
282                                mappings[j].pdbchain,
283                                mappings[j].pdbfile);
284             }
285           }
286         }
287       }
288     }
289   }
290
291   public Annotation[] colourSequenceFromStructure(SequenceI seq, String pdbid)
292   {
293     return null;
294     //THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
295     //UNTIL THE COLOUR BY ANNOTATION IS REWORKED
296    /* Annotation [] annotations = new Annotation[seq.getLength()];
297
298     StructureListener sl;
299     int atomNo = 0;
300     for (int i = 0; i < listeners.size(); i++)
301     {
302       if (listeners.elementAt(i) instanceof StructureListener)
303       {
304         sl = (StructureListener) listeners.elementAt(i);
305
306         for (int j = 0; j < mappings.length; j++)
307         {
308
309           if (mappings[j].sequence == seq
310               && mappings[j].getPdbId().equals(pdbid)
311               && mappings[j].pdbfile.equals(sl.getPdbFile()))
312           {
313             System.out.println(pdbid+" "+mappings[j].getPdbId()
314                 +" "+mappings[j].pdbfile);
315
316             java.awt.Color col;
317             for(int index=0; index<seq.getLength(); index++)
318             {
319               if(jalview.util.Comparison.isGap(seq.getCharAt(index)))
320                 continue;
321
322               atomNo = mappings[j].getAtomNum(seq.findPosition(index));
323               col = java.awt.Color.white;
324               if (atomNo > 0)
325               {
326                 col = sl.getColour(atomNo,
327                                  mappings[j].getPDBResNum(index),
328                                  mappings[j].pdbchain,
329                                  mappings[j].pdbfile);
330               }
331
332               annotations[index] = new Annotation("X",null,' ',0,col);
333             }
334             return annotations;
335           }
336         }
337       }
338     }
339
340     return annotations;*/
341   }
342
343
344   public void structureSelectionChanged()
345   {  }
346
347   public void sequenceSelectionChanged()
348   {  }
349
350   public void sequenceColoursChanged(Object source)
351   {
352     StructureListener sl;
353     for (int i = 0; i < listeners.size(); i++)
354     {
355       if (listeners.elementAt(i) instanceof StructureListener)
356       {
357         sl = (StructureListener) listeners.elementAt(i);
358         sl.updateColours(source);
359       }
360     }
361   }
362
363   public StructureMapping[] getMapping(String pdbfile)
364   {
365     Vector tmp = new Vector();
366     for (int i = 0; i < mappings.length; i++)
367     {
368       if (mappings[i].pdbfile.equals(pdbfile))
369       {
370         tmp.addElement(mappings[i]);
371       }
372     }
373
374     StructureMapping[] ret = new StructureMapping[tmp.size()];
375     for (int i = 0; i < tmp.size(); i++)
376     {
377       ret[i] = (StructureMapping) tmp.elementAt(i);
378     }
379
380     return ret;
381   }
382
383   public String printMapping(String pdbfile)
384   {
385     StringBuffer sb = new StringBuffer();
386     for (int i = 0; i < mappings.length; i++)
387     {
388       if (mappings[i].pdbfile.equals(pdbfile))
389       {
390         sb.append(mappings[i].mappingDetails);
391       }
392     }
393
394     return sb.toString();
395   }
396 }