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.Hashtable;
54 import java.util.IdentityHashMap;
55 import java.util.List;
57 import java.util.Vector;
60 import MCview.PDBChain;
61 import MCview.PDBfile;
63 public class StructureSelectionManager
65 public final static String NEWLINE = System.lineSeparator();
67 static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
69 private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
71 private boolean processSecondaryStructure = false;
73 private boolean secStructServices = false;
75 private boolean addTempFacAnnot = false;
77 private IProgressIndicator progressIndicator;
79 private SiftsClient siftsClient = null;
81 private long progressSessionId;
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>();
93 private Map<String, String> phyre2ModelTemplates = new Hashtable<String, String>();
96 * @return true if will try to use external services for processing secondary
99 public boolean isSecStructServices()
101 return secStructServices;
105 * control use of external services for processing secondary structure
107 * @param secStructServices
109 public void setSecStructServices(boolean secStructServices)
111 this.secStructServices = secStructServices;
115 * flag controlling addition of any kind of structural annotation
117 * @return true if temperature factor annotation will be added
119 public boolean isAddTempFacAnnot()
121 return addTempFacAnnot;
125 * set flag controlling addition of structural annotation
127 * @param addTempFacAnnot
129 public void setAddTempFacAnnot(boolean addTempFacAnnot)
131 this.addTempFacAnnot = addTempFacAnnot;
136 * @return if true, the structure manager will attempt to add secondary
137 * structure lines for unannotated sequences
140 public boolean isProcessSecondaryStructure()
142 return processSecondaryStructure;
146 * Control whether structure manager will try to annotate mapped sequences
147 * with secondary structure from PDB data.
151 public void setProcessSecondaryStructure(boolean enable)
153 processSecondaryStructure = enable;
157 * debug function - write all mappings to stdout
159 public void reportMapping()
161 if (mappings.isEmpty())
163 System.err.println("reportMapping: No PDB/Sequence mappings.");
167 System.err.println("reportMapping: There are " + mappings.size()
170 for (StructureMapping sm : mappings)
172 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
178 * map between the PDB IDs (or structure identifiers) used by Jalview and the
179 * absolute filenames for PDB data that corresponds to it
181 Map<String, String> pdbIdFileName = new HashMap<String, String>();
183 Map<String, String> pdbFileNameId = new HashMap<String, String>();
185 public void registerPDBFile(String idForFile, String absoluteFile)
187 pdbIdFileName.put(idForFile, absoluteFile);
188 pdbFileNameId.put(absoluteFile, idForFile);
191 public String findIdForPDBFile(String idOrFile)
193 String id = pdbFileNameId.get(idOrFile);
197 public String findFileForPDBId(String idOrFile)
199 String id = pdbIdFileName.get(idOrFile);
203 public boolean isPDBFileRegistered(String idOrFile)
205 return pdbFileNameId.containsKey(idOrFile)
206 || pdbIdFileName.containsKey(idOrFile);
209 private static StructureSelectionManager nullProvider = null;
211 public static StructureSelectionManager getStructureSelectionManager(
212 StructureSelectionManagerProvider context)
216 if (nullProvider == null)
218 if (instances != null)
222 .getString("error.implementation_error_structure_selection_manager_null"),
223 new NullPointerException(MessageManager
224 .getString("exception.ssm_context_is_null")));
228 nullProvider = new StructureSelectionManager();
233 if (instances == null)
235 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
237 StructureSelectionManager instance = instances.get(context);
238 if (instance == null)
240 if (nullProvider != null)
242 instance = nullProvider;
246 instance = new StructureSelectionManager();
248 instances.put(context, instance);
254 * flag controlling whether SeqMappings are relayed from received sequence
255 * mouse over events to other sequences
257 boolean relaySeqMappings = true;
260 * Enable or disable relay of seqMapping events to other sequences. You might
261 * want to do this if there are many sequence mappings and the host computer
266 public void setRelaySeqMappings(boolean relay)
268 relaySeqMappings = relay;
272 * get the state of the relay seqMappings flag.
274 * @return true if sequence mouse overs are being relayed to other mapped
277 public boolean isRelaySeqMappingsEnabled()
279 return relaySeqMappings;
282 Vector listeners = new Vector();
285 * register a listener for alignment sequence mouseover events
289 public void addStructureViewerListener(Object svl)
291 if (!listeners.contains(svl))
293 listeners.addElement(svl);
298 * Returns the file name for a mapped PDB id (or null if not mapped).
303 public String alreadyMappedToFile(String pdbid)
305 for (StructureMapping sm : mappings)
307 if (sm.getPdbId().equals(pdbid))
316 * Import structure data and register a structure mapping for broadcasting
317 * colouring, mouseovers and selection events (convenience wrapper).
320 * - one or more sequences to be mapped to pdbFile
321 * @param targetChains
322 * - optional chain specification for mapping each sequence to pdb
323 * (may be nill, individual elements may be nill)
325 * - structure data resource
327 * - how to resolve data from resource
328 * @return null or the structure data parsed as a pdb file
330 synchronized public StructureFile setMapping(SequenceI[] sequence,
331 String[] targetChains, String pdbFile, DataSourceType protocol,
332 IProgressIndicator progress)
334 return computeMapping(true, sequence, targetChains, pdbFile, protocol,
340 * create sequence structure mappings between each sequence and the given
341 * pdbFile (retrieved via the given protocol).
343 * @param forStructureView
344 * when true, record the mapping for use in mouseOvers
346 * @param sequenceArray
347 * - one or more sequences to be mapped to pdbFile
348 * @param targetChainIds
349 * - optional chain specification for mapping each sequence to pdb
350 * (may be null, individual elements may be null)
352 * - structure data resource
354 * - how to resolve data from resource
355 * @return null or the structure data parsed as a pdb file
357 synchronized public StructureFile setMapping(boolean forStructureView,
358 SequenceI[] sequenceArray, String[] targetChainIds,
359 String pdbFile, DataSourceType protocol)
361 return computeMapping(forStructureView, sequenceArray, targetChainIds,
362 pdbFile, protocol, null);
365 synchronized public StructureFile computeMapping(
366 boolean forStructureView, SequenceI[] sequenceArray,
367 String[] targetChainIds, String pdbFile, DataSourceType protocol,
368 IProgressIndicator progress)
370 long progressSessionId = System.currentTimeMillis() * 3;
372 * There will be better ways of doing this in the future, for now we'll use
373 * the tried and tested MCview pdb mapping
375 boolean parseSecStr = processSecondaryStructure;
376 if (isPDBFileRegistered(pdbFile))
378 for (SequenceI sq : sequenceArray)
381 while (ds.getDatasetSequence() != null)
383 ds = ds.getDatasetSequence();
386 if (ds.getAnnotation() != null)
388 for (AlignmentAnnotation ala : ds.getAnnotation())
390 // false if any annotation present from this structure
391 // JBPNote this fails for jmol/chimera view because the *file* is
392 // passed, not the structure data ID -
393 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
401 StructureFile pdb = null;
402 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
405 pdb = new JmolParser(pdbFile, protocol);
407 if (pdb.getId() != null && pdb.getId().trim().length() > 0
408 && DataSourceType.FILE == protocol)
410 registerPDBFile(pdb.getId().trim(), pdbFile);
412 // if PDBId is unavailable then skip SIFTS mapping execution path
413 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
415 } catch (Exception ex)
417 ex.printStackTrace();
425 siftsClient = new SiftsClient(pdb);
427 } catch (SiftsException e)
429 isMapUsingSIFTs = false;
433 String targetChainId;
434 for (int s = 0; s < sequenceArray.length; s++)
436 boolean infChain = true;
437 final SequenceI seq = sequenceArray[s];
439 while (ds.getDatasetSequence() != null)
441 ds = ds.getDatasetSequence();
444 if (targetChainIds != null && targetChainIds[s] != null)
447 targetChainId = targetChainIds[s];
449 else if (seq.getName().indexOf("|") > -1)
451 targetChainId = seq.getName().substring(
452 seq.getName().lastIndexOf("|") + 1);
453 if (targetChainId.length() > 1)
455 if (targetChainId.trim().length() == 0)
461 // not a valid chain identifier
472 * Attempt pairwise alignment of the sequence with each chain in the PDB,
473 * and remember the highest scoring chain
476 AlignSeq maxAlignseq = null;
477 String maxChainId = " ";
478 PDBChain maxChain = null;
479 boolean first = true;
480 for (PDBChain chain : pdb.getChains())
482 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
485 continue; // don't try to map chains don't match.
487 // TODO: correctly determine sequence type for mixed na/peptide
489 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
490 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
493 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
494 // as.calcScoreMatrix();
495 // as.traceAlignment();
497 if (first || as.maxscore > max
498 || (as.maxscore == max && chain.id.equals(targetChainId)))
504 maxChainId = chain.id;
507 if (maxChain == null)
512 if (protocol.equals(DataSourceType.PASTE))
514 pdbFile = "INLINE" + pdb.getId();
516 boolean phyre2Template = isPhyre2Template(pdbFile);
517 List<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
518 if (!phyre2Template && isMapUsingSIFTs && seq.isProtein())
520 if (progress!=null) {
521 progress.setProgressBar(MessageManager
522 .getString("status.obtaining_mapping_with_sifts"),
525 jalview.datamodel.Mapping sqmpping = maxAlignseq
526 .getMappingFromS1(false);
527 if (targetChainId != null && !targetChainId.trim().isEmpty())
529 StructureMapping siftsMapping;
532 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
533 pdb, maxChain, sqmpping, maxAlignseq);
534 seqToStrucMapping.add(siftsMapping);
535 maxChain.makeExactMapping(maxAlignseq, seq);
536 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
538 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
539 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
541 } catch (SiftsException e)
543 // fall back to NW alignment
544 System.err.println(e.getMessage());
545 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
546 targetChainId, maxChain, pdb, maxAlignseq);
547 seqToStrucMapping.add(nwMapping);
548 maxChain.makeExactMapping(maxAlignseq, seq);
549 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
551 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
552 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
553 } catch (Exception e)
560 List<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
561 for (PDBChain chain : pdb.getChains())
565 StructureMapping siftsMapping = getStructureMapping(seq,
566 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
567 foundSiftsMappings.add(siftsMapping);
568 } catch (SiftsException e)
570 System.err.println(e.getMessage());
571 } catch (Exception e)
576 if (!foundSiftsMappings.isEmpty())
578 seqToStrucMapping.addAll(foundSiftsMappings);
579 maxChain.makeExactMapping(maxAlignseq, seq);
580 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
582 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
584 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
588 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
589 maxChainId, maxChain, pdb, maxAlignseq);
590 seqToStrucMapping.add(nwMapping);
591 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
593 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
594 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
598 else if (phyre2Template)
600 setProgressBar(null);
601 setProgressBar(MessageManager
602 .getString("status.obtaining_mapping_with_phyre2_template_alignment"));
603 String fastaFile = getPhyre2FastaFileFor(pdbFile);
604 StructureMapping phyre2ModelMapping = new Phyre2Client(pdb)
605 .getStructureMapping(seq, pdbFile, fastaFile, " ");
606 seqToStrucMapping.add(phyre2ModelMapping);
607 maxChain.makeExactMapping(maxAlignseq, seq);
608 maxChain.transferRESNUMFeatures(seq, null);
609 jalview.datamodel.Mapping sqmpping = maxAlignseq
610 .getMappingFromS1(false);
611 maxChain.transferResidueAnnotation(phyre2ModelMapping, sqmpping);
612 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
616 if (progress != null)
618 progress.setProgressBar(MessageManager
619 .getString("status.obtaining_mapping_with_nw_alignment"),
622 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
623 maxChainId, maxChain, pdb, maxAlignseq);
624 seqToStrucMapping.add(nwMapping);
625 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
629 if (forStructureView)
631 mappings.addAll(seqToStrucMapping);
637 public void registerPhyre2Template(String phyre2Template,
638 String fastaMappingFile)
640 phyre2ModelTemplates.put(phyre2Template, fastaMappingFile);
644 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
649 * @param targetChainId
655 * @throws SiftsException
657 private StructureMapping getStructureMapping(SequenceI seq,
658 String pdbFile, String targetChainId, StructureFile pdb,
659 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
660 AlignSeq maxAlignseq) throws Exception
662 StructureMapping curChainMapping = siftsClient
663 .getStructureMapping(seq, pdbFile, targetChainId);
666 PDBChain chain = pdb.findChain(targetChainId);
669 chain.transferResidueAnnotation(curChainMapping, sqmpping);
671 } catch (Exception e)
675 return curChainMapping;
678 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
679 String maxChainId, PDBChain maxChain, StructureFile pdb,
680 AlignSeq maxAlignseq)
682 final StringBuilder mappingDetails = new StringBuilder(128);
683 mappingDetails.append(NEWLINE).append(
684 "Sequence \u27f7 Structure mapping details");
685 mappingDetails.append(NEWLINE);
687 .append("Method: inferred with Needleman & Wunsch alignment");
688 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
689 .append(NEWLINE).append("Sequence = ")
690 .append(maxChain.sequence.getSequenceAsString());
691 mappingDetails.append(NEWLINE).append("No of residues = ")
692 .append(maxChain.residues.size()).append(NEWLINE)
694 PrintStream ps = new PrintStream(System.out)
697 public void print(String x)
699 mappingDetails.append(x);
703 public void println()
705 mappingDetails.append(NEWLINE);
709 maxAlignseq.printAlignment(ps);
711 mappingDetails.append(NEWLINE).append("PDB start/end ");
712 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
714 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
715 mappingDetails.append(NEWLINE).append("SEQ start/end ");
716 mappingDetails.append(
717 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
719 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
720 + (seq.getStart() - 1)));
721 mappingDetails.append(NEWLINE);
722 maxChain.makeExactMapping(maxAlignseq, seq);
723 jalview.datamodel.Mapping sqmpping = maxAlignseq
724 .getMappingFromS1(false);
725 maxChain.transferRESNUMFeatures(seq, null);
727 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
734 Atom tmp = maxChain.atoms.elementAt(index);
735 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
736 && tmp.alignmentMapping != -1)
738 resNum = tmp.resNumber;
739 insCode = tmp.insCode;
740 if (tmp.alignmentMapping >= -1)
742 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
748 } while (index < maxChain.atoms.size());
750 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
751 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
752 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
756 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
758 listeners.removeElement(svl);
759 if (svl instanceof SequenceListener)
761 for (int i = 0; i < listeners.size(); i++)
763 if (listeners.elementAt(i) instanceof StructureListener)
765 ((StructureListener) listeners.elementAt(i))
766 .releaseReferences(svl);
771 if (pdbfiles == null)
777 * Remove mappings to the closed listener's PDB files, but first check if
778 * another listener is still interested
780 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
782 StructureListener sl;
783 for (int i = 0; i < listeners.size(); i++)
785 if (listeners.elementAt(i) instanceof StructureListener)
787 sl = (StructureListener) listeners.elementAt(i);
788 for (String pdbfile : sl.getPdbFile())
790 pdbs.remove(pdbfile);
796 * Rebuild the mappings set, retaining only those which are for 'other' PDB
801 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
802 for (StructureMapping sm : mappings)
804 if (!pdbs.contains(sm.pdbfile))
815 * Propagate mouseover of a single position in a structure
821 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
823 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
824 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
825 mouseOverStructure(atoms);
829 * Propagate mouseover or selection of multiple positions in a structure
833 public void mouseOverStructure(List<AtomSpec> atoms)
835 if (listeners == null)
837 // old or prematurely sent event
840 boolean hasSequenceListener = false;
841 for (int i = 0; i < listeners.size(); i++)
843 if (listeners.elementAt(i) instanceof SequenceListener)
845 hasSequenceListener = true;
848 if (!hasSequenceListener)
853 SearchResultsI results = new SearchResults();
854 for (AtomSpec atom : atoms)
856 SequenceI lastseq = null;
858 for (StructureMapping sm : mappings)
860 if (sm.pdbfile.equals(atom.getPdbFile())
861 && sm.pdbchain.equals(atom.getChain()))
863 int indexpos = sm.getSeqPos(atom.getPdbResNum());
864 if (lastipos != indexpos && lastseq != sm.sequence)
866 results.addResult(sm.sequence, indexpos, indexpos);
868 lastseq = sm.sequence;
869 // construct highlighted sequence list
870 for (AlignedCodonFrame acf : seqmappings)
872 acf.markMappedRegion(sm.sequence, indexpos, results);
878 for (Object li : listeners)
880 if (li instanceof SequenceListener)
882 ((SequenceListener) li).highlightSequence(results);
888 * highlight regions associated with a position (indexpos) in seq
891 * the sequence that the mouse over occurred on
893 * the absolute position being mouseovered in seq (0 to seq.length())
895 * the sequence position (if -1, seq.findPosition is called to
896 * resolve the residue number)
898 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
901 boolean hasSequenceListeners = handlingVamsasMo
902 || !seqmappings.isEmpty();
903 SearchResultsI results = null;
906 seqPos = seq.findPosition(indexpos);
908 for (int i = 0; i < listeners.size(); i++)
910 Object listener = listeners.elementAt(i);
911 if (listener == source)
913 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
914 // Temporary fudge with SequenceListener.getVamsasSource()
917 if (listener instanceof StructureListener)
919 highlightStructure((StructureListener) listener, seq, seqPos);
923 if (listener instanceof SequenceListener)
925 final SequenceListener seqListener = (SequenceListener) listener;
926 if (hasSequenceListeners
927 && seqListener.getVamsasSource() != source)
929 if (relaySeqMappings)
933 results = MappingUtils.buildSearchResults(seq, seqPos,
936 if (handlingVamsasMo)
938 results.addResult(seq, seqPos, seqPos);
941 if (!results.isEmpty())
943 seqListener.highlightSequence(results);
948 else if (listener instanceof VamsasListener && !handlingVamsasMo)
950 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
953 else if (listener instanceof SecondaryStructureListener)
955 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
963 * Send suitable messages to a StructureListener to highlight atoms
964 * corresponding to the given sequence position(s)
970 public void highlightStructure(StructureListener sl, SequenceI seq,
973 if (!sl.isListeningFor(seq))
978 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
979 for (StructureMapping sm : mappings)
981 if (sm.sequence == seq
982 || sm.sequence == seq.getDatasetSequence()
983 || (sm.sequence.getDatasetSequence() != null && sm.sequence
984 .getDatasetSequence() == seq.getDatasetSequence()))
986 for (int index : positions)
988 atomNo = sm.getAtomNum(index);
992 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
993 .getPDBResNum(index), atomNo));
998 sl.highlightAtoms(atoms);
1002 * true if a mouse over event from an external (ie Vamsas) source is being
1005 boolean handlingVamsasMo = false;
1010 * as mouseOverSequence but only route event to SequenceListeners
1014 * in an alignment sequence
1016 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
1017 VamsasSource source)
1019 handlingVamsasMo = true;
1020 long msg = sequenceI.hashCode() * (1 + position);
1024 mouseOverSequence(sequenceI, position, -1, source);
1026 handlingVamsasMo = false;
1029 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1033 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1034 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1036 * Annotation [] annotations = new Annotation[seq.getLength()];
1038 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1039 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1040 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1042 * for (int j = 0; j < mappings.length; j++) {
1044 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1045 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1046 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1047 * "+mappings[j].pdbfile);
1049 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1050 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1052 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1053 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1054 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1055 * mappings[j].pdbfile); }
1057 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1058 * annotations; } } } }
1060 * return annotations;
1064 public void structureSelectionChanged()
1068 public void sequenceSelectionChanged()
1072 public void sequenceColoursChanged(Object source)
1074 StructureListener sl;
1075 for (int i = 0; i < listeners.size(); i++)
1077 if (listeners.elementAt(i) instanceof StructureListener)
1079 sl = (StructureListener) listeners.elementAt(i);
1080 sl.updateColours(source);
1085 public StructureMapping[] getMapping(String pdbfile)
1087 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1088 for (StructureMapping sm : mappings)
1090 if (sm.pdbfile.equals(pdbfile))
1095 return tmp.toArray(new StructureMapping[tmp.size()]);
1099 * Returns a readable description of all mappings for the given pdbfile to any
1100 * of the given sequences
1106 public String printMappings(String pdbfile, List<SequenceI> seqs)
1108 if (pdbfile == null || seqs == null || seqs.isEmpty())
1113 StringBuilder sb = new StringBuilder(64);
1114 for (StructureMapping sm : mappings)
1116 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1118 sb.append(sm.mappingDetails);
1120 // separator makes it easier to read multiple mappings
1121 sb.append("=====================");
1127 return sb.toString();
1131 * Remove the given mapping
1135 public void deregisterMapping(AlignedCodonFrame acf)
1139 boolean removed = seqmappings.remove(acf);
1140 if (removed && seqmappings.isEmpty())
1142 System.out.println("All mappings removed");
1148 * Add each of the given codonFrames to the stored set, if not aready present.
1152 public void registerMappings(List<AlignedCodonFrame> mappings)
1154 if (mappings != null)
1156 for (AlignedCodonFrame acf : mappings)
1158 registerMapping(acf);
1164 * Add the given mapping to the stored set, unless already stored.
1166 public void registerMapping(AlignedCodonFrame acf)
1170 if (!seqmappings.contains(acf))
1172 seqmappings.add(acf);
1178 * Resets this object to its initial state by removing all registered
1179 * listeners, codon mappings, PDB file mappings
1181 public void resetAll()
1183 if (mappings != null)
1187 if (seqmappings != null)
1189 seqmappings.clear();
1191 if (sel_listeners != null)
1193 sel_listeners.clear();
1195 if (listeners != null)
1199 if (commandListeners != null)
1201 commandListeners.clear();
1203 if (view_listeners != null)
1205 view_listeners.clear();
1207 if (pdbFileNameId != null)
1209 pdbFileNameId.clear();
1211 if (pdbIdFileName != null)
1213 pdbIdFileName.clear();
1217 public void addSelectionListener(SelectionListener selecter)
1219 if (!sel_listeners.contains(selecter))
1221 sel_listeners.add(selecter);
1225 public void removeSelectionListener(SelectionListener toremove)
1227 if (sel_listeners.contains(toremove))
1229 sel_listeners.remove(toremove);
1233 public synchronized void sendSelection(
1234 jalview.datamodel.SequenceGroup selection,
1235 jalview.datamodel.ColumnSelection colsel, SelectionSource source)
1237 for (SelectionListener slis : sel_listeners)
1241 slis.selection(selection, colsel, source);
1246 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1248 public synchronized void sendViewPosition(
1249 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1250 int startSeq, int endSeq)
1253 if (view_listeners != null && view_listeners.size() > 0)
1255 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1257 while (listeners.hasMoreElements())
1259 AlignmentViewPanelListener slis = listeners.nextElement();
1262 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1270 * release all references associated with this manager provider
1272 * @param jalviewLite
1274 public static void release(StructureSelectionManagerProvider jalviewLite)
1276 // synchronized (instances)
1278 if (instances == null)
1282 StructureSelectionManager mnger = (instances.get(jalviewLite));
1285 instances.remove(jalviewLite);
1289 } catch (Throwable x)
1296 public void registerPDBEntry(PDBEntry pdbentry)
1298 if (pdbentry.getFile() != null
1299 && pdbentry.getFile().trim().length() > 0)
1301 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1305 public void addCommandListener(CommandListener cl)
1307 if (!commandListeners.contains(cl))
1309 commandListeners.add(cl);
1313 public boolean hasCommandListener(CommandListener cl)
1315 return this.commandListeners.contains(cl);
1318 public boolean removeCommandListener(CommandListener l)
1320 return commandListeners.remove(l);
1324 * Forward a command to any command listeners (except for the command's
1328 * the command to be broadcast (in its form after being performed)
1330 * if true, the command was being 'undone'
1333 public void commandPerformed(CommandI command, boolean undo,
1334 VamsasSource source)
1336 for (CommandListener listener : commandListeners)
1338 listener.mirrorCommand(command, undo, this, source);
1343 * Returns a new CommandI representing the given command as mapped to the
1344 * given sequences. If no mapping could be made, or the command is not of a
1345 * mappable kind, returns null.
1353 public CommandI mapCommand(CommandI command, boolean undo,
1354 final AlignmentI mapTo, char gapChar)
1356 if (command instanceof EditCommand)
1358 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1359 mapTo, gapChar, seqmappings);
1361 else if (command instanceof OrderCommand)
1363 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1364 mapTo, seqmappings);
1369 public IProgressIndicator getProgressIndicator()
1371 return progressIndicator;
1374 public void setProgressIndicator(IProgressIndicator progressIndicator)
1376 this.progressIndicator = progressIndicator;
1379 public long getProgressSessionId()
1381 return progressSessionId;
1384 public void setProgressSessionId(long progressSessionId)
1386 this.progressSessionId = progressSessionId;
1389 public void setProgressBar(String message)
1391 if (progressIndicator == null)
1395 progressIndicator.setProgressBar(message, progressSessionId);
1398 public List<AlignedCodonFrame> getSequenceMappings()
1403 public boolean isPhyre2Template(String structureFile)
1405 if (structureFile == null || phyre2ModelTemplates == null
1406 || phyre2ModelTemplates.isEmpty())
1410 return phyre2ModelTemplates.get(structureFile) != null
1411 && !phyre2ModelTemplates.get(structureFile).isEmpty();
1414 public String getPhyre2FastaFileFor(String structureFile)
1416 return phyre2ModelTemplates.get(structureFile);
1420 public static StructureSelectionManager getStructureSelectionManager()
1422 return instances.values().iterator().next();