2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.structure;
23 import jalview.analysis.AlignSeq;
24 import jalview.api.StructureSelectionManagerProvider;
25 import jalview.commands.CommandI;
26 import jalview.commands.EditCommand;
27 import jalview.commands.OrderCommand;
28 import jalview.datamodel.AlignedCodonFrame;
29 import jalview.datamodel.AlignmentAnnotation;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.Annotation;
32 import jalview.datamodel.PDBEntry;
33 import jalview.datamodel.SearchResults;
34 import jalview.datamodel.SearchResultsI;
35 import jalview.datamodel.SequenceI;
36 import jalview.ext.jmol.JmolParser;
37 import jalview.gui.IProgressIndicator;
38 import jalview.io.DataSourceType;
39 import jalview.io.StructureFile;
40 import jalview.util.MappingUtils;
41 import jalview.util.MessageManager;
42 import jalview.ws.phyre2.Phyre2Client;
43 import jalview.ws.sifts.SiftsClient;
44 import jalview.ws.sifts.SiftsException;
45 import jalview.ws.sifts.SiftsSettings;
47 import java.io.PrintStream;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.Collections;
51 import java.util.Enumeration;
52 import java.util.HashMap;
53 import java.util.IdentityHashMap;
54 import java.util.List;
56 import java.util.Vector;
59 import MCview.PDBChain;
60 import MCview.PDBfile;
62 public class StructureSelectionManager
64 public final static String NEWLINE = System.lineSeparator();
66 static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
68 private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
70 private boolean processSecondaryStructure = false;
72 private boolean secStructServices = false;
74 private boolean addTempFacAnnot = false;
76 private IProgressIndicator progressIndicator;
78 private SiftsClient siftsClient = null;
80 private long progressSessionId;
82 private boolean mappingForPhyre2Model;
85 * Set of any registered mappings between (dataset) sequences.
87 private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
89 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
91 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
94 * @return true if will try to use external services for processing secondary
97 public boolean isSecStructServices()
99 return secStructServices;
103 * control use of external services for processing secondary structure
105 * @param secStructServices
107 public void setSecStructServices(boolean secStructServices)
109 this.secStructServices = secStructServices;
113 * flag controlling addition of any kind of structural annotation
115 * @return true if temperature factor annotation will be added
117 public boolean isAddTempFacAnnot()
119 return addTempFacAnnot;
123 * set flag controlling addition of structural annotation
125 * @param addTempFacAnnot
127 public void setAddTempFacAnnot(boolean addTempFacAnnot)
129 this.addTempFacAnnot = addTempFacAnnot;
134 * @return if true, the structure manager will attempt to add secondary
135 * structure lines for unannotated sequences
138 public boolean isProcessSecondaryStructure()
140 return processSecondaryStructure;
144 * Control whether structure manager will try to annotate mapped sequences
145 * with secondary structure from PDB data.
149 public void setProcessSecondaryStructure(boolean enable)
151 processSecondaryStructure = enable;
155 * debug function - write all mappings to stdout
157 public void reportMapping()
159 if (mappings.isEmpty())
161 System.err.println("reportMapping: No PDB/Sequence mappings.");
165 System.err.println("reportMapping: There are " + mappings.size()
168 for (StructureMapping sm : mappings)
170 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
176 * map between the PDB IDs (or structure identifiers) used by Jalview and the
177 * absolute filenames for PDB data that corresponds to it
179 Map<String, String> pdbIdFileName = new HashMap<String, String>();
181 Map<String, String> pdbFileNameId = new HashMap<String, String>();
183 public void registerPDBFile(String idForFile, String absoluteFile)
185 pdbIdFileName.put(idForFile, absoluteFile);
186 pdbFileNameId.put(absoluteFile, idForFile);
189 public String findIdForPDBFile(String idOrFile)
191 String id = pdbFileNameId.get(idOrFile);
195 public String findFileForPDBId(String idOrFile)
197 String id = pdbIdFileName.get(idOrFile);
201 public boolean isPDBFileRegistered(String idOrFile)
203 return pdbFileNameId.containsKey(idOrFile)
204 || pdbIdFileName.containsKey(idOrFile);
207 private static StructureSelectionManager nullProvider = null;
209 public static StructureSelectionManager getStructureSelectionManager(
210 StructureSelectionManagerProvider context)
214 if (nullProvider == null)
216 if (instances != null)
220 .getString("error.implementation_error_structure_selection_manager_null"),
221 new NullPointerException(MessageManager
222 .getString("exception.ssm_context_is_null")));
226 nullProvider = new StructureSelectionManager();
231 if (instances == null)
233 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
235 StructureSelectionManager instance = instances.get(context);
236 if (instance == null)
238 if (nullProvider != null)
240 instance = nullProvider;
244 instance = new StructureSelectionManager();
246 instances.put(context, instance);
252 * flag controlling whether SeqMappings are relayed from received sequence
253 * mouse over events to other sequences
255 boolean relaySeqMappings = true;
258 * Enable or disable relay of seqMapping events to other sequences. You might
259 * want to do this if there are many sequence mappings and the host computer
264 public void setRelaySeqMappings(boolean relay)
266 relaySeqMappings = relay;
270 * get the state of the relay seqMappings flag.
272 * @return true if sequence mouse overs are being relayed to other mapped
275 public boolean isRelaySeqMappingsEnabled()
277 return relaySeqMappings;
280 Vector listeners = new Vector();
283 * register a listener for alignment sequence mouseover events
287 public void addStructureViewerListener(Object svl)
289 if (!listeners.contains(svl))
291 listeners.addElement(svl);
296 * Returns the file name for a mapped PDB id (or null if not mapped).
301 public String alreadyMappedToFile(String pdbid)
303 for (StructureMapping sm : mappings)
305 if (sm.getPdbId().equals(pdbid))
314 * Import structure data and register a structure mapping for broadcasting
315 * colouring, mouseovers and selection events (convenience wrapper).
318 * - one or more sequences to be mapped to pdbFile
319 * @param targetChains
320 * - optional chain specification for mapping each sequence to pdb
321 * (may be nill, individual elements may be nill)
323 * - structure data resource
325 * - how to resolve data from resource
326 * @return null or the structure data parsed as a pdb file
328 synchronized public StructureFile setMapping(SequenceI[] sequence,
329 String[] targetChains, String pdbFile, DataSourceType protocol,
330 IProgressIndicator progress)
332 return computeMapping(true, sequence, targetChains, pdbFile, protocol,
338 * create sequence structure mappings between each sequence and the given
339 * pdbFile (retrieved via the given protocol).
341 * @param forStructureView
342 * when true, record the mapping for use in mouseOvers
344 * @param sequenceArray
345 * - one or more sequences to be mapped to pdbFile
346 * @param targetChainIds
347 * - optional chain specification for mapping each sequence to pdb
348 * (may be null, individual elements may be null)
350 * - structure data resource
352 * - how to resolve data from resource
353 * @return null or the structure data parsed as a pdb file
355 synchronized public StructureFile setMapping(boolean forStructureView,
356 SequenceI[] sequenceArray, String[] targetChainIds,
357 String pdbFile, DataSourceType protocol)
359 return computeMapping(forStructureView, sequenceArray, targetChainIds,
360 pdbFile, protocol, null);
363 synchronized public StructureFile computeMapping(
364 boolean forStructureView, SequenceI[] sequenceArray,
365 String[] targetChainIds, String pdbFile, DataSourceType protocol,
366 IProgressIndicator progress)
368 long progressSessionId = System.currentTimeMillis() * 3;
370 * There will be better ways of doing this in the future, for now we'll use
371 * the tried and tested MCview pdb mapping
373 boolean parseSecStr = processSecondaryStructure;
374 if (isPDBFileRegistered(pdbFile))
376 for (SequenceI sq : sequenceArray)
379 while (ds.getDatasetSequence() != null)
381 ds = ds.getDatasetSequence();
384 if (ds.getAnnotation() != null)
386 for (AlignmentAnnotation ala : ds.getAnnotation())
388 // false if any annotation present from this structure
389 // JBPNote this fails for jmol/chimera view because the *file* is
390 // passed, not the structure data ID -
391 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
399 StructureFile pdb = null;
400 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
403 pdb = new JmolParser(pdbFile, protocol);
405 if (pdb.getId() != null && pdb.getId().trim().length() > 0
406 && DataSourceType.FILE == protocol)
408 registerPDBFile(pdb.getId().trim(), pdbFile);
410 // if PDBId is unavailable then skip SIFTS mapping execution path
411 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
413 } catch (Exception ex)
415 ex.printStackTrace();
423 siftsClient = new SiftsClient(pdb);
425 } catch (SiftsException e)
427 isMapUsingSIFTs = false;
431 String targetChainId;
432 for (int s = 0; s < sequenceArray.length; s++)
434 boolean infChain = true;
435 final SequenceI seq = sequenceArray[s];
437 while (ds.getDatasetSequence() != null)
439 ds = ds.getDatasetSequence();
442 if (targetChainIds != null && targetChainIds[s] != null)
445 targetChainId = targetChainIds[s];
447 else if (seq.getName().indexOf("|") > -1)
449 targetChainId = seq.getName().substring(
450 seq.getName().lastIndexOf("|") + 1);
451 if (targetChainId.length() > 1)
453 if (targetChainId.trim().length() == 0)
459 // not a valid chain identifier
470 * Attempt pairwise alignment of the sequence with each chain in the PDB,
471 * and remember the highest scoring chain
474 AlignSeq maxAlignseq = null;
475 String maxChainId = " ";
476 PDBChain maxChain = null;
477 boolean first = true;
478 for (PDBChain chain : pdb.getChains())
480 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
483 continue; // don't try to map chains don't match.
485 // TODO: correctly determine sequence type for mixed na/peptide
487 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
488 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
491 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
492 // as.calcScoreMatrix();
493 // as.traceAlignment();
495 if (first || as.maxscore > max
496 || (as.maxscore == max && chain.id.equals(targetChainId)))
502 maxChainId = chain.id;
505 if (maxChain == null)
510 if (protocol.equals(DataSourceType.PASTE))
512 pdbFile = "INLINE" + pdb.getId();
515 List<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
516 if (!isMappingForPhyre2Model() && isMapUsingSIFTs && seq.isProtein())
518 if (progress!=null) {
519 progress.setProgressBar(MessageManager
520 .getString("status.obtaining_mapping_with_sifts"),
523 jalview.datamodel.Mapping sqmpping = maxAlignseq
524 .getMappingFromS1(false);
525 if (targetChainId != null && !targetChainId.trim().isEmpty())
527 StructureMapping siftsMapping;
530 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
531 pdb, maxChain, sqmpping, maxAlignseq);
532 seqToStrucMapping.add(siftsMapping);
533 maxChain.makeExactMapping(maxAlignseq, seq);
534 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
536 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
537 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
539 } catch (SiftsException e)
541 // fall back to NW alignment
542 System.err.println(e.getMessage());
543 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
544 targetChainId, maxChain, pdb, maxAlignseq);
545 seqToStrucMapping.add(nwMapping);
546 maxChain.makeExactMapping(maxAlignseq, seq);
547 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
549 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
550 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
551 } catch (Exception e)
558 List<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
559 for (PDBChain chain : pdb.getChains())
563 StructureMapping siftsMapping = getStructureMapping(seq,
564 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
565 foundSiftsMappings.add(siftsMapping);
566 } catch (SiftsException e)
568 System.err.println(e.getMessage());
569 } catch (Exception e)
574 if (!foundSiftsMappings.isEmpty())
576 seqToStrucMapping.addAll(foundSiftsMappings);
577 maxChain.makeExactMapping(maxAlignseq, seq);
578 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
580 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
582 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
586 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
587 maxChainId, maxChain, pdb, maxAlignseq);
588 seqToStrucMapping.add(nwMapping);
589 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
591 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
592 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
596 else if (isMappingForPhyre2Model())
598 setProgressBar(null);
599 setProgressBar(MessageManager
600 .getString("status.obtaining_mapping_with_phyre2_template_alignment"));
601 StructureMapping phyre2ModelMapping = new Phyre2Client(pdb)
602 .getStructureMapping(seq, pdbFile, " ");
604 seqToStrucMapping.add(phyre2ModelMapping);
605 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
609 if (progress != null)
611 progress.setProgressBar(MessageManager
612 .getString("status.obtaining_mapping_with_nw_alignment"),
615 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
616 maxChainId, maxChain, pdb, maxAlignseq);
617 seqToStrucMapping.add(nwMapping);
618 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
622 if (forStructureView)
624 mappings.addAll(seqToStrucMapping);
630 private boolean isCIFFile(String filename)
632 String fileExt = filename.substring(filename.lastIndexOf(".") + 1,
634 return "cif".equalsIgnoreCase(fileExt);
638 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
643 * @param targetChainId
649 * @throws SiftsException
651 private StructureMapping getStructureMapping(SequenceI seq,
652 String pdbFile, String targetChainId, StructureFile pdb,
653 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
654 AlignSeq maxAlignseq) throws Exception
656 StructureMapping curChainMapping = siftsClient
657 .getStructureMapping(seq, pdbFile, targetChainId);
660 PDBChain chain = pdb.findChain(targetChainId);
663 chain.transferResidueAnnotation(curChainMapping, sqmpping);
665 } catch (Exception e)
669 return curChainMapping;
672 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
673 String maxChainId, PDBChain maxChain, StructureFile pdb,
674 AlignSeq maxAlignseq)
676 final StringBuilder mappingDetails = new StringBuilder(128);
677 mappingDetails.append(NEWLINE).append(
678 "Sequence \u27f7 Structure mapping details");
679 mappingDetails.append(NEWLINE);
681 .append("Method: inferred with Needleman & Wunsch alignment");
682 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
683 .append(NEWLINE).append("Sequence = ")
684 .append(maxChain.sequence.getSequenceAsString());
685 mappingDetails.append(NEWLINE).append("No of residues = ")
686 .append(maxChain.residues.size()).append(NEWLINE)
688 PrintStream ps = new PrintStream(System.out)
691 public void print(String x)
693 mappingDetails.append(x);
697 public void println()
699 mappingDetails.append(NEWLINE);
703 maxAlignseq.printAlignment(ps);
705 mappingDetails.append(NEWLINE).append("PDB start/end ");
706 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
708 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
709 mappingDetails.append(NEWLINE).append("SEQ start/end ");
710 mappingDetails.append(
711 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
713 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
714 + (seq.getStart() - 1)));
715 mappingDetails.append(NEWLINE);
716 maxChain.makeExactMapping(maxAlignseq, seq);
717 jalview.datamodel.Mapping sqmpping = maxAlignseq
718 .getMappingFromS1(false);
719 maxChain.transferRESNUMFeatures(seq, null);
721 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
728 Atom tmp = maxChain.atoms.elementAt(index);
729 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
730 && tmp.alignmentMapping != -1)
732 resNum = tmp.resNumber;
733 insCode = tmp.insCode;
734 if (tmp.alignmentMapping >= -1)
736 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
742 } while (index < maxChain.atoms.size());
744 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
745 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
746 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
750 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
752 listeners.removeElement(svl);
753 if (svl instanceof SequenceListener)
755 for (int i = 0; i < listeners.size(); i++)
757 if (listeners.elementAt(i) instanceof StructureListener)
759 ((StructureListener) listeners.elementAt(i))
760 .releaseReferences(svl);
765 if (pdbfiles == null)
771 * Remove mappings to the closed listener's PDB files, but first check if
772 * another listener is still interested
774 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
776 StructureListener sl;
777 for (int i = 0; i < listeners.size(); i++)
779 if (listeners.elementAt(i) instanceof StructureListener)
781 sl = (StructureListener) listeners.elementAt(i);
782 for (String pdbfile : sl.getPdbFile())
784 pdbs.remove(pdbfile);
790 * Rebuild the mappings set, retaining only those which are for 'other' PDB
795 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
796 for (StructureMapping sm : mappings)
798 if (!pdbs.contains(sm.pdbfile))
809 * Propagate mouseover of a single position in a structure
815 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
817 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
818 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
819 mouseOverStructure(atoms);
823 * Propagate mouseover or selection of multiple positions in a structure
827 public void mouseOverStructure(List<AtomSpec> atoms)
829 if (listeners == null)
831 // old or prematurely sent event
834 boolean hasSequenceListener = false;
835 for (int i = 0; i < listeners.size(); i++)
837 if (listeners.elementAt(i) instanceof SequenceListener)
839 hasSequenceListener = true;
842 if (!hasSequenceListener)
847 SearchResultsI results = new SearchResults();
848 for (AtomSpec atom : atoms)
850 SequenceI lastseq = null;
852 for (StructureMapping sm : mappings)
854 if (sm.pdbfile.equals(atom.getPdbFile())
855 && sm.pdbchain.equals(atom.getChain()))
857 int indexpos = sm.getSeqPos(atom.getPdbResNum());
858 if (lastipos != indexpos && lastseq != sm.sequence)
860 results.addResult(sm.sequence, indexpos, indexpos);
862 lastseq = sm.sequence;
863 // construct highlighted sequence list
864 for (AlignedCodonFrame acf : seqmappings)
866 acf.markMappedRegion(sm.sequence, indexpos, results);
872 for (Object li : listeners)
874 if (li instanceof SequenceListener)
876 ((SequenceListener) li).highlightSequence(results);
882 * highlight regions associated with a position (indexpos) in seq
885 * the sequence that the mouse over occurred on
887 * the absolute position being mouseovered in seq (0 to seq.length())
889 * the sequence position (if -1, seq.findPosition is called to
890 * resolve the residue number)
892 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
895 boolean hasSequenceListeners = handlingVamsasMo
896 || !seqmappings.isEmpty();
897 SearchResultsI results = null;
900 seqPos = seq.findPosition(indexpos);
902 for (int i = 0; i < listeners.size(); i++)
904 Object listener = listeners.elementAt(i);
905 if (listener == source)
907 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
908 // Temporary fudge with SequenceListener.getVamsasSource()
911 if (listener instanceof StructureListener)
913 highlightStructure((StructureListener) listener, seq, seqPos);
917 if (listener instanceof SequenceListener)
919 final SequenceListener seqListener = (SequenceListener) listener;
920 if (hasSequenceListeners
921 && seqListener.getVamsasSource() != source)
923 if (relaySeqMappings)
927 results = MappingUtils.buildSearchResults(seq, seqPos,
930 if (handlingVamsasMo)
932 results.addResult(seq, seqPos, seqPos);
935 if (!results.isEmpty())
937 seqListener.highlightSequence(results);
942 else if (listener instanceof VamsasListener && !handlingVamsasMo)
944 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
947 else if (listener instanceof SecondaryStructureListener)
949 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
957 * Send suitable messages to a StructureListener to highlight atoms
958 * corresponding to the given sequence position(s)
964 public void highlightStructure(StructureListener sl, SequenceI seq,
967 if (!sl.isListeningFor(seq))
972 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
973 for (StructureMapping sm : mappings)
975 if (sm.sequence == seq
976 || sm.sequence == seq.getDatasetSequence()
977 || (sm.sequence.getDatasetSequence() != null && sm.sequence
978 .getDatasetSequence() == seq.getDatasetSequence()))
980 for (int index : positions)
982 atomNo = sm.getAtomNum(index);
986 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
987 .getPDBResNum(index), atomNo));
992 sl.highlightAtoms(atoms);
996 * true if a mouse over event from an external (ie Vamsas) source is being
999 boolean handlingVamsasMo = false;
1004 * as mouseOverSequence but only route event to SequenceListeners
1008 * in an alignment sequence
1010 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
1011 VamsasSource source)
1013 handlingVamsasMo = true;
1014 long msg = sequenceI.hashCode() * (1 + position);
1018 mouseOverSequence(sequenceI, position, -1, source);
1020 handlingVamsasMo = false;
1023 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1027 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1028 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1030 * Annotation [] annotations = new Annotation[seq.getLength()];
1032 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1033 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1034 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1036 * for (int j = 0; j < mappings.length; j++) {
1038 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1039 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1040 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1041 * "+mappings[j].pdbfile);
1043 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1044 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1046 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1047 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1048 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1049 * mappings[j].pdbfile); }
1051 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1052 * annotations; } } } }
1054 * return annotations;
1058 public void structureSelectionChanged()
1062 public void sequenceSelectionChanged()
1066 public void sequenceColoursChanged(Object source)
1068 StructureListener sl;
1069 for (int i = 0; i < listeners.size(); i++)
1071 if (listeners.elementAt(i) instanceof StructureListener)
1073 sl = (StructureListener) listeners.elementAt(i);
1074 sl.updateColours(source);
1079 public StructureMapping[] getMapping(String pdbfile)
1081 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1082 for (StructureMapping sm : mappings)
1084 if (sm.pdbfile.equals(pdbfile))
1089 return tmp.toArray(new StructureMapping[tmp.size()]);
1093 * Returns a readable description of all mappings for the given pdbfile to any
1094 * of the given sequences
1100 public String printMappings(String pdbfile, List<SequenceI> seqs)
1102 if (pdbfile == null || seqs == null || seqs.isEmpty())
1107 StringBuilder sb = new StringBuilder(64);
1108 for (StructureMapping sm : mappings)
1110 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1112 sb.append(sm.mappingDetails);
1114 // separator makes it easier to read multiple mappings
1115 sb.append("=====================");
1121 return sb.toString();
1125 * Remove the given mapping
1129 public void deregisterMapping(AlignedCodonFrame acf)
1133 boolean removed = seqmappings.remove(acf);
1134 if (removed && seqmappings.isEmpty())
1136 System.out.println("All mappings removed");
1142 * Add each of the given codonFrames to the stored set, if not aready present.
1146 public void registerMappings(List<AlignedCodonFrame> mappings)
1148 if (mappings != null)
1150 for (AlignedCodonFrame acf : mappings)
1152 registerMapping(acf);
1158 * Add the given mapping to the stored set, unless already stored.
1160 public void registerMapping(AlignedCodonFrame acf)
1164 if (!seqmappings.contains(acf))
1166 seqmappings.add(acf);
1172 * Resets this object to its initial state by removing all registered
1173 * listeners, codon mappings, PDB file mappings
1175 public void resetAll()
1177 if (mappings != null)
1181 if (seqmappings != null)
1183 seqmappings.clear();
1185 if (sel_listeners != null)
1187 sel_listeners.clear();
1189 if (listeners != null)
1193 if (commandListeners != null)
1195 commandListeners.clear();
1197 if (view_listeners != null)
1199 view_listeners.clear();
1201 if (pdbFileNameId != null)
1203 pdbFileNameId.clear();
1205 if (pdbIdFileName != null)
1207 pdbIdFileName.clear();
1211 public void addSelectionListener(SelectionListener selecter)
1213 if (!sel_listeners.contains(selecter))
1215 sel_listeners.add(selecter);
1219 public void removeSelectionListener(SelectionListener toremove)
1221 if (sel_listeners.contains(toremove))
1223 sel_listeners.remove(toremove);
1227 public synchronized void sendSelection(
1228 jalview.datamodel.SequenceGroup selection,
1229 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1231 for (SelectionListener slis : sel_listeners)
1235 slis.selection(selection, colsel, source);
1240 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1242 public synchronized void sendViewPosition(
1243 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1244 int startSeq, int endSeq)
1247 if (view_listeners != null && view_listeners.size() > 0)
1249 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1251 while (listeners.hasMoreElements())
1253 AlignmentViewPanelListener slis = listeners.nextElement();
1256 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1264 * release all references associated with this manager provider
1266 * @param jalviewLite
1268 public static void release(StructureSelectionManagerProvider jalviewLite)
1270 // synchronized (instances)
1272 if (instances == null)
1276 StructureSelectionManager mnger = (instances.get(jalviewLite));
1279 instances.remove(jalviewLite);
1283 } catch (Throwable x)
1290 public void registerPDBEntry(PDBEntry pdbentry)
1292 if (pdbentry.getFile() != null
1293 && pdbentry.getFile().trim().length() > 0)
1295 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1299 public void addCommandListener(CommandListener cl)
1301 if (!commandListeners.contains(cl))
1303 commandListeners.add(cl);
1307 public boolean hasCommandListener(CommandListener cl)
1309 return this.commandListeners.contains(cl);
1312 public boolean removeCommandListener(CommandListener l)
1314 return commandListeners.remove(l);
1318 * Forward a command to any command listeners (except for the command's
1322 * the command to be broadcast (in its form after being performed)
1324 * if true, the command was being 'undone'
1327 public void commandPerformed(CommandI command, boolean undo,
1328 VamsasSource source)
1330 for (CommandListener listener : commandListeners)
1332 listener.mirrorCommand(command, undo, this, source);
1337 * Returns a new CommandI representing the given command as mapped to the
1338 * given sequences. If no mapping could be made, or the command is not of a
1339 * mappable kind, returns null.
1347 public CommandI mapCommand(CommandI command, boolean undo,
1348 final AlignmentI mapTo, char gapChar)
1350 if (command instanceof EditCommand)
1352 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1353 mapTo, gapChar, seqmappings);
1355 else if (command instanceof OrderCommand)
1357 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1358 mapTo, seqmappings);
1363 public IProgressIndicator getProgressIndicator()
1365 return progressIndicator;
1368 public void setProgressIndicator(IProgressIndicator progressIndicator)
1370 this.progressIndicator = progressIndicator;
1373 public long getProgressSessionId()
1375 return progressSessionId;
1378 public void setProgressSessionId(long progressSessionId)
1380 this.progressSessionId = progressSessionId;
1383 public void setProgressBar(String message)
1385 if (progressIndicator == null)
1389 progressIndicator.setProgressBar(message, progressSessionId);
1392 public List<AlignedCodonFrame> getSequenceMappings()
1397 public boolean isMappingForPhyre2Model()
1399 return mappingForPhyre2Model;
1402 public void setMappingForPhyre2Model(boolean mappingForPhyre2Model)
1404 this.mappingForPhyre2Model = mappingForPhyre2Model;
1407 public static StructureSelectionManager getStructureSelectionManager()
1409 return instances.values().iterator().next();