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.HiddenColumns;
33 import jalview.datamodel.PDBEntry;
34 import jalview.datamodel.SearchResults;
35 import jalview.datamodel.SearchResultsI;
36 import jalview.datamodel.SequenceI;
37 import jalview.ext.jmol.JmolParser;
38 import jalview.gui.IProgressIndicator;
39 import jalview.io.AppletFormatAdapter;
40 import jalview.io.DataSourceType;
41 import jalview.io.StructureFile;
42 import jalview.util.MappingUtils;
43 import jalview.util.MessageManager;
44 import jalview.ws.phyre2.Phyre2Client;
45 import jalview.ws.sifts.SiftsClient;
46 import jalview.ws.sifts.SiftsException;
47 import jalview.ws.sifts.SiftsSettings;
49 import java.io.PrintStream;
50 import java.util.ArrayList;
51 import java.util.Arrays;
52 import java.util.Collections;
53 import java.util.Enumeration;
54 import java.util.HashMap;
55 import java.util.Hashtable;
56 import java.util.IdentityHashMap;
57 import java.util.List;
59 import java.util.Vector;
62 import MCview.PDBChain;
63 import MCview.PDBfile;
65 public class StructureSelectionManager
67 public final static String NEWLINE = System.lineSeparator();
69 static IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager> instances;
71 private List<StructureMapping> mappings = new ArrayList<StructureMapping>();
73 private boolean processSecondaryStructure = false;
75 private boolean secStructServices = false;
77 private boolean addTempFacAnnot = false;
79 private IProgressIndicator progressIndicator;
81 private SiftsClient siftsClient = null;
83 private long progressSessionId;
87 * Set of any registered mappings between (dataset) sequences.
89 private List<AlignedCodonFrame> seqmappings = new ArrayList<AlignedCodonFrame>();
91 private List<CommandListener> commandListeners = new ArrayList<CommandListener>();
93 private List<SelectionListener> sel_listeners = new ArrayList<SelectionListener>();
95 private Map<String, String> phyre2ModelTemplates = new Hashtable<String, String>();
98 * @return true if will try to use external services for processing secondary
101 public boolean isSecStructServices()
103 return secStructServices;
107 * control use of external services for processing secondary structure
109 * @param secStructServices
111 public void setSecStructServices(boolean secStructServices)
113 this.secStructServices = secStructServices;
117 * flag controlling addition of any kind of structural annotation
119 * @return true if temperature factor annotation will be added
121 public boolean isAddTempFacAnnot()
123 return addTempFacAnnot;
127 * set flag controlling addition of structural annotation
129 * @param addTempFacAnnot
131 public void setAddTempFacAnnot(boolean addTempFacAnnot)
133 this.addTempFacAnnot = addTempFacAnnot;
138 * @return if true, the structure manager will attempt to add secondary
139 * structure lines for unannotated sequences
142 public boolean isProcessSecondaryStructure()
144 return processSecondaryStructure;
148 * Control whether structure manager will try to annotate mapped sequences
149 * with secondary structure from PDB data.
153 public void setProcessSecondaryStructure(boolean enable)
155 processSecondaryStructure = enable;
159 * debug function - write all mappings to stdout
161 public void reportMapping()
163 if (mappings.isEmpty())
165 System.err.println("reportMapping: No PDB/Sequence mappings.");
169 System.err.println("reportMapping: There are " + mappings.size()
172 for (StructureMapping sm : mappings)
174 System.err.println("mapping " + i++ + " : " + sm.pdbfile);
180 * map between the PDB IDs (or structure identifiers) used by Jalview and the
181 * absolute filenames for PDB data that corresponds to it
183 Map<String, String> pdbIdFileName = new HashMap<String, String>();
185 Map<String, String> pdbFileNameId = new HashMap<String, String>();
187 public void registerPDBFile(String idForFile, String absoluteFile)
189 pdbIdFileName.put(idForFile, absoluteFile);
190 pdbFileNameId.put(absoluteFile, idForFile);
193 public String findIdForPDBFile(String idOrFile)
195 String id = pdbFileNameId.get(idOrFile);
199 public String findFileForPDBId(String idOrFile)
201 String id = pdbIdFileName.get(idOrFile);
205 public boolean isPDBFileRegistered(String idOrFile)
207 return pdbFileNameId.containsKey(idOrFile)
208 || pdbIdFileName.containsKey(idOrFile);
211 private static StructureSelectionManager nullProvider = null;
213 public static StructureSelectionManager getStructureSelectionManager(
214 StructureSelectionManagerProvider context)
218 if (nullProvider == null)
220 if (instances != null)
224 .getString("error.implementation_error_structure_selection_manager_null"),
225 new NullPointerException(MessageManager
226 .getString("exception.ssm_context_is_null")));
230 nullProvider = new StructureSelectionManager();
235 if (instances == null)
237 instances = new java.util.IdentityHashMap<StructureSelectionManagerProvider, StructureSelectionManager>();
239 StructureSelectionManager instance = instances.get(context);
240 if (instance == null)
242 if (nullProvider != null)
244 instance = nullProvider;
248 instance = new StructureSelectionManager();
250 instances.put(context, instance);
256 * flag controlling whether SeqMappings are relayed from received sequence
257 * mouse over events to other sequences
259 boolean relaySeqMappings = true;
262 * Enable or disable relay of seqMapping events to other sequences. You might
263 * want to do this if there are many sequence mappings and the host computer
268 public void setRelaySeqMappings(boolean relay)
270 relaySeqMappings = relay;
274 * get the state of the relay seqMappings flag.
276 * @return true if sequence mouse overs are being relayed to other mapped
279 public boolean isRelaySeqMappingsEnabled()
281 return relaySeqMappings;
284 Vector listeners = new Vector();
287 * register a listener for alignment sequence mouseover events
291 public void addStructureViewerListener(Object svl)
293 if (!listeners.contains(svl))
295 listeners.addElement(svl);
300 * Returns the file name for a mapped PDB id (or null if not mapped).
305 public String alreadyMappedToFile(String pdbid)
307 for (StructureMapping sm : mappings)
309 if (sm.getPdbId().equals(pdbid))
318 * Import structure data and register a structure mapping for broadcasting
319 * colouring, mouseovers and selection events (convenience wrapper).
322 * - one or more sequences to be mapped to pdbFile
323 * @param targetChains
324 * - optional chain specification for mapping each sequence to pdb
325 * (may be nill, individual elements may be nill)
327 * - structure data resource
329 * - how to resolve data from resource
330 * @return null or the structure data parsed as a pdb file
332 synchronized public StructureFile setMapping(SequenceI[] sequence,
333 String[] targetChains, String pdbFile, DataSourceType protocol,
334 IProgressIndicator progress)
336 return computeMapping(true, sequence, targetChains, pdbFile, protocol,
342 * create sequence structure mappings between each sequence and the given
343 * pdbFile (retrieved via the given protocol).
345 * @param forStructureView
346 * when true, record the mapping for use in mouseOvers
348 * @param sequenceArray
349 * - one or more sequences to be mapped to pdbFile
350 * @param targetChainIds
351 * - optional chain specification for mapping each sequence to pdb
352 * (may be null, individual elements may be null)
354 * - structure data resource
356 * - how to resolve data from resource
357 * @return null or the structure data parsed as a pdb file
359 synchronized public StructureFile setMapping(boolean forStructureView,
360 SequenceI[] sequenceArray, String[] targetChainIds,
361 String pdbFile, DataSourceType protocol)
363 return computeMapping(forStructureView, sequenceArray, targetChainIds,
364 pdbFile, protocol, null);
367 synchronized public StructureFile computeMapping(
368 boolean forStructureView, SequenceI[] sequenceArray,
369 String[] targetChainIds, String pdbFile, DataSourceType protocol,
370 IProgressIndicator progress)
372 long progressSessionId = System.currentTimeMillis() * 3;
374 * There will be better ways of doing this in the future, for now we'll use
375 * the tried and tested MCview pdb mapping
377 boolean parseSecStr = processSecondaryStructure;
378 if (isPDBFileRegistered(pdbFile))
380 for (SequenceI sq : sequenceArray)
383 while (ds.getDatasetSequence() != null)
385 ds = ds.getDatasetSequence();
388 if (ds.getAnnotation() != null)
390 for (AlignmentAnnotation ala : ds.getAnnotation())
392 // false if any annotation present from this structure
393 // JBPNote this fails for jmol/chimera view because the *file* is
394 // passed, not the structure data ID -
395 if (PDBfile.isCalcIdForFile(ala, findIdForPDBFile(pdbFile)))
403 StructureFile pdb = null;
404 boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
407 pdb = new JmolParser(pdbFile,
408 AppletFormatAdapter.checkProtocol(pdbFile));
411 if (pdb.getId() != null && pdb.getId().trim().length() > 0
412 && DataSourceType.FILE == protocol)
414 registerPDBFile(pdb.getId().trim(), pdbFile);
416 // if PDBId is unavailable then skip SIFTS mapping execution path
417 isMapUsingSIFTs = isMapUsingSIFTs && pdb.isPPDBIdAvailable();
419 } catch (Exception ex)
421 ex.printStackTrace();
429 siftsClient = new SiftsClient(pdb);
431 } catch (SiftsException e)
433 isMapUsingSIFTs = false;
437 String targetChainId;
438 for (int s = 0; s < sequenceArray.length; s++)
440 boolean infChain = true;
441 final SequenceI seq = sequenceArray[s];
443 while (ds.getDatasetSequence() != null)
445 ds = ds.getDatasetSequence();
448 if (targetChainIds != null && targetChainIds[s] != null)
451 targetChainId = targetChainIds[s];
453 else if (seq.getName().indexOf("|") > -1)
455 targetChainId = seq.getName().substring(
456 seq.getName().lastIndexOf("|") + 1);
457 if (targetChainId.length() > 1)
459 if (targetChainId.trim().length() == 0)
461 targetChainId = StructureMapping.NO_CHAIN;
465 // not a valid chain identifier
476 * Attempt pairwise alignment of the sequence with each chain in the PDB,
477 * and remember the highest scoring chain
480 AlignSeq maxAlignseq = null;
481 String maxChainId = StructureMapping.NO_CHAIN; // space
482 PDBChain maxChain = null;
483 boolean first = true;
484 for (PDBChain chain : pdb.getChains())
486 if (targetChainId.length() > 0 && !targetChainId.equals(chain.id)
489 continue; // don't try to map chains don't match.
491 // TODO: correctly determine sequence type for mixed na/peptide
493 final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP;
494 AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence,
497 // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type);
498 // as.calcScoreMatrix();
499 // as.traceAlignment();
501 if (first || as.maxscore > max
502 || (as.maxscore == max && chain.id.equals(targetChainId)))
508 maxChainId = chain.id;
511 if (maxChain == null)
516 if (protocol.equals(DataSourceType.PASTE))
518 pdbFile = "INLINE" + pdb.getId();
520 boolean phyre2Template = isPhyre2Template(pdbFile);
521 List<StructureMapping> seqToStrucMapping = new ArrayList<StructureMapping>();
522 if (!phyre2Template && isMapUsingSIFTs && seq.isProtein())
524 if (progress!=null) {
525 progress.setProgressBar(MessageManager
526 .getString("status.obtaining_mapping_with_sifts"),
529 jalview.datamodel.Mapping sqmpping = maxAlignseq
530 .getMappingFromS1(false);
531 if (targetChainId != null && !targetChainId.trim().isEmpty())
533 StructureMapping siftsMapping;
536 siftsMapping = getStructureMapping(seq, pdbFile, targetChainId,
537 pdb, maxChain, sqmpping, maxAlignseq);
538 seqToStrucMapping.add(siftsMapping);
539 maxChain.makeExactMapping(maxAlignseq, seq);
540 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
542 maxChain.transferResidueAnnotation(siftsMapping, sqmpping);
543 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
545 } catch (SiftsException e)
547 // fall back to NW alignment
548 System.err.println(e.getMessage());
549 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
550 targetChainId, maxChain, pdb, maxAlignseq);
551 seqToStrucMapping.add(nwMapping);
552 maxChain.makeExactMapping(maxAlignseq, seq);
553 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
555 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
556 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
557 } catch (Exception e)
564 List<StructureMapping> foundSiftsMappings = new ArrayList<StructureMapping>();
565 for (PDBChain chain : pdb.getChains())
569 StructureMapping siftsMapping = getStructureMapping(seq,
570 pdbFile, chain.id, pdb, chain, sqmpping, maxAlignseq);
571 foundSiftsMappings.add(siftsMapping);
572 } catch (SiftsException e)
574 System.err.println(e.getMessage());
575 } catch (Exception e)
580 if (!foundSiftsMappings.isEmpty())
582 seqToStrucMapping.addAll(foundSiftsMappings);
583 maxChain.makeExactMapping(maxAlignseq, seq);
584 maxChain.transferRESNUMFeatures(seq, null);// FIXME: is this
586 maxChain.transferResidueAnnotation(foundSiftsMappings.get(0),
588 ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0));
592 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
593 maxChainId, maxChain, pdb, maxAlignseq);
594 seqToStrucMapping.add(nwMapping);
595 maxChain.transferRESNUMFeatures(seq, null); // FIXME: is this
597 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
598 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
602 else if (phyre2Template)
604 setProgressBar(null);
605 setProgressBar(MessageManager
606 .getString("status.obtaining_mapping_with_phyre2_template_alignment"));
607 String fastaFile = getPhyre2FastaFileFor(pdbFile);
608 StructureMapping phyre2ModelMapping = new Phyre2Client(pdb)
609 .getStructureMapping(seq, pdbFile, fastaFile,
610 StructureMapping.NO_CHAIN);
611 seqToStrucMapping.add(phyre2ModelMapping);
612 maxChain.makeExactMapping(maxAlignseq, seq);
613 maxChain.transferRESNUMFeatures(seq, null);
614 jalview.datamodel.Mapping sqmpping = maxAlignseq
615 .getMappingFromS1(false);
616 maxChain.transferResidueAnnotation(phyre2ModelMapping, sqmpping);
617 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
621 if (progress != null)
623 progress.setProgressBar(MessageManager
624 .getString("status.obtaining_mapping_with_nw_alignment"),
627 StructureMapping nwMapping = getNWMappings(seq, pdbFile,
628 maxChainId, maxChain, pdb, maxAlignseq);
629 seqToStrucMapping.add(nwMapping);
630 ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0));
634 if (forStructureView)
636 mappings.addAll(seqToStrucMapping);
642 public void registerPhyre2Template(String phyre2Template,
643 String fastaMappingFile)
645 phyre2ModelTemplates.put(phyre2Template, fastaMappingFile);
649 * retrieve a mapping for seq from SIFTs using associated DBRefEntry for
654 * @param targetChainId
660 * @throws SiftsException
662 private StructureMapping getStructureMapping(SequenceI seq,
663 String pdbFile, String targetChainId, StructureFile pdb,
664 PDBChain maxChain, jalview.datamodel.Mapping sqmpping,
665 AlignSeq maxAlignseq) throws Exception
667 StructureMapping curChainMapping = siftsClient
668 .getSiftsStructureMapping(seq, pdbFile, targetChainId);
671 PDBChain chain = pdb.findChain(targetChainId);
674 chain.transferResidueAnnotation(curChainMapping, sqmpping);
676 } catch (Exception e)
680 return curChainMapping;
683 private StructureMapping getNWMappings(SequenceI seq, String pdbFile,
684 String maxChainId, PDBChain maxChain, StructureFile pdb,
685 AlignSeq maxAlignseq)
687 final StringBuilder mappingDetails = new StringBuilder(128);
688 mappingDetails.append(NEWLINE).append(
689 "Sequence \u27f7 Structure mapping details");
690 mappingDetails.append(NEWLINE);
692 .append("Method: inferred with Needleman & Wunsch alignment");
693 mappingDetails.append(NEWLINE).append("PDB Sequence is :")
694 .append(NEWLINE).append("Sequence = ")
695 .append(maxChain.sequence.getSequenceAsString());
696 mappingDetails.append(NEWLINE).append("No of residues = ")
697 .append(maxChain.residues.size()).append(NEWLINE)
699 PrintStream ps = new PrintStream(System.out)
702 public void print(String x)
704 mappingDetails.append(x);
708 public void println()
710 mappingDetails.append(NEWLINE);
714 maxAlignseq.printAlignment(ps);
716 mappingDetails.append(NEWLINE).append("PDB start/end ");
717 mappingDetails.append(String.valueOf(maxAlignseq.seq2start))
719 mappingDetails.append(String.valueOf(maxAlignseq.seq2end));
720 mappingDetails.append(NEWLINE).append("SEQ start/end ");
721 mappingDetails.append(
722 String.valueOf(maxAlignseq.seq1start + (seq.getStart() - 1)))
724 mappingDetails.append(String.valueOf(maxAlignseq.seq1end
725 + (seq.getStart() - 1)));
726 mappingDetails.append(NEWLINE);
727 maxChain.makeExactMapping(maxAlignseq, seq);
728 jalview.datamodel.Mapping sqmpping = maxAlignseq
729 .getMappingFromS1(false);
730 maxChain.transferRESNUMFeatures(seq, null);
732 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
739 Atom tmp = maxChain.atoms.elementAt(index);
740 if ((resNum != tmp.resNumber || insCode != tmp.insCode)
741 && tmp.alignmentMapping != -1)
743 resNum = tmp.resNumber;
744 insCode = tmp.insCode;
745 if (tmp.alignmentMapping >= -1)
747 mapping.put(tmp.alignmentMapping + 1, new int[] { tmp.resNumber,
753 } while (index < maxChain.atoms.size());
755 StructureMapping nwMapping = new StructureMapping(seq, pdbFile,
756 pdb.getId(), maxChainId, mapping, mappingDetails.toString());
757 maxChain.transferResidueAnnotation(nwMapping, sqmpping);
761 public void removeStructureViewerListener(Object svl, String[] pdbfiles)
763 listeners.removeElement(svl);
764 if (svl instanceof SequenceListener)
766 for (int i = 0; i < listeners.size(); i++)
768 if (listeners.elementAt(i) instanceof StructureListener)
770 ((StructureListener) listeners.elementAt(i))
771 .releaseReferences(svl);
776 if (pdbfiles == null)
782 * Remove mappings to the closed listener's PDB files, but first check if
783 * another listener is still interested
785 List<String> pdbs = new ArrayList<String>(Arrays.asList(pdbfiles));
787 StructureListener sl;
788 for (int i = 0; i < listeners.size(); i++)
790 if (listeners.elementAt(i) instanceof StructureListener)
792 sl = (StructureListener) listeners.elementAt(i);
793 for (String pdbfile : sl.getStructureFiles())
795 pdbs.remove(pdbfile);
801 * Rebuild the mappings set, retaining only those which are for 'other' PDB
806 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
807 for (StructureMapping sm : mappings)
809 if (!pdbs.contains(sm.pdbfile))
820 * Propagate mouseover of a single position in a structure
826 public void mouseOverStructure(int pdbResNum, String chain, String pdbfile)
828 AtomSpec atomSpec = new AtomSpec(pdbfile, chain, pdbResNum, 0);
829 List<AtomSpec> atoms = Collections.singletonList(atomSpec);
830 mouseOverStructure(atoms);
834 * Propagate mouseover or selection of multiple positions in a structure
838 public void mouseOverStructure(List<AtomSpec> atoms)
840 if (listeners == null)
842 // old or prematurely sent event
845 boolean hasSequenceListener = false;
846 for (int i = 0; i < listeners.size(); i++)
848 if (listeners.elementAt(i) instanceof SequenceListener)
850 hasSequenceListener = true;
853 if (!hasSequenceListener)
858 SearchResultsI results = findAlignmentPositionsForStructurePositions(atoms);
859 for (Object li : listeners)
861 if (li instanceof SequenceListener)
863 ((SequenceListener) li).highlightSequence(results);
869 * Constructs a SearchResults object holding regions (if any) in the Jalview
870 * alignment which have a mapping to the structure viewer positions in the
876 public SearchResultsI findAlignmentPositionsForStructurePositions(
877 List<AtomSpec> atoms)
879 SearchResultsI results = new SearchResults();
880 for (AtomSpec atom : atoms)
882 SequenceI lastseq = null;
884 for (StructureMapping sm : mappings)
886 if (sm.pdbfile.equals(atom.getPdbFile())
887 && sm.pdbchain.equals(atom.getChain()))
889 int indexpos = sm.getSeqPos(atom.getPdbResNum());
890 if (lastipos != indexpos || lastseq != sm.sequence)
892 results.addResult(sm.sequence, indexpos, indexpos);
894 lastseq = sm.sequence;
895 // construct highlighted sequence list
896 for (AlignedCodonFrame acf : seqmappings)
898 acf.markMappedRegion(sm.sequence, indexpos, results);
908 * highlight regions associated with a position (indexpos) in seq
911 * the sequence that the mouse over occurred on
913 * the absolute position being mouseovered in seq (0 to seq.length())
915 * the sequence position (if -1, seq.findPosition is called to
916 * resolve the residue number)
918 public void mouseOverSequence(SequenceI seq, int indexpos, int seqPos,
921 boolean hasSequenceListeners = handlingVamsasMo
922 || !seqmappings.isEmpty();
923 SearchResultsI results = null;
926 seqPos = seq.findPosition(indexpos);
928 for (int i = 0; i < listeners.size(); i++)
930 Object listener = listeners.elementAt(i);
931 if (listener == source)
933 // TODO listener (e.g. SeqPanel) is never == source (AlignViewport)
934 // Temporary fudge with SequenceListener.getVamsasSource()
937 if (listener instanceof StructureListener)
939 highlightStructure((StructureListener) listener, seq, seqPos);
943 if (listener instanceof SequenceListener)
945 final SequenceListener seqListener = (SequenceListener) listener;
946 if (hasSequenceListeners
947 && seqListener.getVamsasSource() != source)
949 if (relaySeqMappings)
953 results = MappingUtils.buildSearchResults(seq, seqPos,
956 if (handlingVamsasMo)
958 results.addResult(seq, seqPos, seqPos);
961 if (!results.isEmpty())
963 seqListener.highlightSequence(results);
968 else if (listener instanceof VamsasListener && !handlingVamsasMo)
970 ((VamsasListener) listener).mouseOverSequence(seq, indexpos,
973 else if (listener instanceof SecondaryStructureListener)
975 ((SecondaryStructureListener) listener).mouseOverSequence(seq,
983 * Send suitable messages to a StructureListener to highlight atoms
984 * corresponding to the given sequence position(s)
990 public void highlightStructure(StructureListener sl, SequenceI seq,
993 if (!sl.isListeningFor(seq))
998 List<AtomSpec> atoms = new ArrayList<AtomSpec>();
999 for (StructureMapping sm : mappings)
1001 if (sm.sequence == seq
1002 || sm.sequence == seq.getDatasetSequence()
1003 || (sm.sequence.getDatasetSequence() != null && sm.sequence
1004 .getDatasetSequence() == seq.getDatasetSequence()))
1006 for (int index : positions)
1008 atomNo = sm.getAtomNum(index);
1012 atoms.add(new AtomSpec(sm.pdbfile, sm.pdbchain, sm
1013 .getPDBResNum(index), atomNo));
1018 sl.highlightAtoms(atoms);
1022 * true if a mouse over event from an external (ie Vamsas) source is being
1025 boolean handlingVamsasMo = false;
1030 * as mouseOverSequence but only route event to SequenceListeners
1034 * in an alignment sequence
1036 public void mouseOverVamsasSequence(SequenceI sequenceI, int position,
1037 VamsasSource source)
1039 handlingVamsasMo = true;
1040 long msg = sequenceI.hashCode() * (1 + position);
1044 mouseOverSequence(sequenceI, position, -1, source);
1046 handlingVamsasMo = false;
1049 public Annotation[] colourSequenceFromStructure(SequenceI seq,
1053 // THIS WILL NOT BE AVAILABLE IN JALVIEW 2.3,
1054 // UNTIL THE COLOUR BY ANNOTATION IS REWORKED
1056 * Annotation [] annotations = new Annotation[seq.getLength()];
1058 * StructureListener sl; int atomNo = 0; for (int i = 0; i <
1059 * listeners.size(); i++) { if (listeners.elementAt(i) instanceof
1060 * StructureListener) { sl = (StructureListener) listeners.elementAt(i);
1062 * for (int j = 0; j < mappings.length; j++) {
1064 * if (mappings[j].sequence == seq && mappings[j].getPdbId().equals(pdbid)
1065 * && mappings[j].pdbfile.equals(sl.getPdbFile())) {
1066 * System.out.println(pdbid+" "+mappings[j].getPdbId() +"
1067 * "+mappings[j].pdbfile);
1069 * java.awt.Color col; for(int index=0; index<seq.getLength(); index++) {
1070 * if(jalview.util.Comparison.isGap(seq.getCharAt(index))) continue;
1072 * atomNo = mappings[j].getAtomNum(seq.findPosition(index)); col =
1073 * java.awt.Color.white; if (atomNo > 0) { col = sl.getColour(atomNo,
1074 * mappings[j].getPDBResNum(index), mappings[j].pdbchain,
1075 * mappings[j].pdbfile); }
1077 * annotations[index] = new Annotation("X",null,' ',0,col); } return
1078 * annotations; } } } }
1080 * return annotations;
1084 public void structureSelectionChanged()
1088 public void sequenceSelectionChanged()
1092 public void sequenceColoursChanged(Object source)
1094 StructureListener sl;
1095 for (int i = 0; i < listeners.size(); i++)
1097 if (listeners.elementAt(i) instanceof StructureListener)
1099 sl = (StructureListener) listeners.elementAt(i);
1100 sl.updateColours(source);
1105 public StructureMapping[] getMapping(String pdbfile)
1107 List<StructureMapping> tmp = new ArrayList<StructureMapping>();
1108 for (StructureMapping sm : mappings)
1110 if (sm.pdbfile.equals(pdbfile))
1115 return tmp.toArray(new StructureMapping[tmp.size()]);
1119 * Returns a readable description of all mappings for the given pdbfile to any
1120 * of the given sequences
1126 public String printMappings(String pdbfile, List<SequenceI> seqs)
1128 if (pdbfile == null || seqs == null || seqs.isEmpty())
1133 StringBuilder sb = new StringBuilder(64);
1134 for (StructureMapping sm : mappings)
1136 if (sm.pdbfile.equals(pdbfile) && seqs.contains(sm.sequence))
1138 sb.append(sm.mappingDetails);
1140 // separator makes it easier to read multiple mappings
1141 sb.append("=====================");
1147 return sb.toString();
1151 * Remove the given mapping
1155 public void deregisterMapping(AlignedCodonFrame acf)
1159 boolean removed = seqmappings.remove(acf);
1160 if (removed && seqmappings.isEmpty())
1162 System.out.println("All mappings removed");
1168 * Add each of the given codonFrames to the stored set, if not aready present.
1172 public void registerMappings(List<AlignedCodonFrame> mappings)
1174 if (mappings != null)
1176 for (AlignedCodonFrame acf : mappings)
1178 registerMapping(acf);
1184 * Add the given mapping to the stored set, unless already stored.
1186 public void registerMapping(AlignedCodonFrame acf)
1190 if (!seqmappings.contains(acf))
1192 seqmappings.add(acf);
1198 * Resets this object to its initial state by removing all registered
1199 * listeners, codon mappings, PDB file mappings
1201 public void resetAll()
1203 if (mappings != null)
1207 if (seqmappings != null)
1209 seqmappings.clear();
1211 if (sel_listeners != null)
1213 sel_listeners.clear();
1215 if (listeners != null)
1219 if (commandListeners != null)
1221 commandListeners.clear();
1223 if (view_listeners != null)
1225 view_listeners.clear();
1227 if (pdbFileNameId != null)
1229 pdbFileNameId.clear();
1231 if (pdbIdFileName != null)
1233 pdbIdFileName.clear();
1237 public void addSelectionListener(SelectionListener selecter)
1239 if (!sel_listeners.contains(selecter))
1241 sel_listeners.add(selecter);
1245 public void removeSelectionListener(SelectionListener toremove)
1247 if (sel_listeners.contains(toremove))
1249 sel_listeners.remove(toremove);
1253 public synchronized void sendSelection(
1254 jalview.datamodel.SequenceGroup selection,
1255 jalview.datamodel.ColumnSelection colsel, HiddenColumns hidden,
1256 SelectionSource source)
1258 for (SelectionListener slis : sel_listeners)
1262 slis.selection(selection, colsel, hidden, source);
1267 Vector<AlignmentViewPanelListener> view_listeners = new Vector<AlignmentViewPanelListener>();
1269 public synchronized void sendViewPosition(
1270 jalview.api.AlignmentViewPanel source, int startRes, int endRes,
1271 int startSeq, int endSeq)
1274 if (view_listeners != null && view_listeners.size() > 0)
1276 Enumeration<AlignmentViewPanelListener> listeners = view_listeners
1278 while (listeners.hasMoreElements())
1280 AlignmentViewPanelListener slis = listeners.nextElement();
1283 slis.viewPosition(startRes, endRes, startSeq, endSeq, source);
1291 * release all references associated with this manager provider
1293 * @param jalviewLite
1295 public static void release(StructureSelectionManagerProvider jalviewLite)
1297 // synchronized (instances)
1299 if (instances == null)
1303 StructureSelectionManager mnger = (instances.get(jalviewLite));
1306 instances.remove(jalviewLite);
1310 } catch (Throwable x)
1317 public void registerPDBEntry(PDBEntry pdbentry)
1319 if (pdbentry.getFile() != null
1320 && pdbentry.getFile().trim().length() > 0)
1322 registerPDBFile(pdbentry.getId(), pdbentry.getFile());
1326 public void addCommandListener(CommandListener cl)
1328 if (!commandListeners.contains(cl))
1330 commandListeners.add(cl);
1334 public boolean hasCommandListener(CommandListener cl)
1336 return this.commandListeners.contains(cl);
1339 public boolean removeCommandListener(CommandListener l)
1341 return commandListeners.remove(l);
1345 * Forward a command to any command listeners (except for the command's
1349 * the command to be broadcast (in its form after being performed)
1351 * if true, the command was being 'undone'
1354 public void commandPerformed(CommandI command, boolean undo,
1355 VamsasSource source)
1357 for (CommandListener listener : commandListeners)
1359 listener.mirrorCommand(command, undo, this, source);
1364 * Returns a new CommandI representing the given command as mapped to the
1365 * given sequences. If no mapping could be made, or the command is not of a
1366 * mappable kind, returns null.
1374 public CommandI mapCommand(CommandI command, boolean undo,
1375 final AlignmentI mapTo, char gapChar)
1377 if (command instanceof EditCommand)
1379 return MappingUtils.mapEditCommand((EditCommand) command, undo,
1380 mapTo, gapChar, seqmappings);
1382 else if (command instanceof OrderCommand)
1384 return MappingUtils.mapOrderCommand((OrderCommand) command, undo,
1385 mapTo, seqmappings);
1390 public IProgressIndicator getProgressIndicator()
1392 return progressIndicator;
1395 public void setProgressIndicator(IProgressIndicator progressIndicator)
1397 this.progressIndicator = progressIndicator;
1400 public long getProgressSessionId()
1402 return progressSessionId;
1405 public void setProgressSessionId(long progressSessionId)
1407 this.progressSessionId = progressSessionId;
1410 public void setProgressBar(String message)
1412 if (progressIndicator == null)
1416 progressIndicator.setProgressBar(message, progressSessionId);
1419 public List<AlignedCodonFrame> getSequenceMappings()
1424 public boolean isPhyre2Template(String structureFile)
1426 if (structureFile == null || phyre2ModelTemplates == null
1427 || phyre2ModelTemplates.isEmpty())
1431 return phyre2ModelTemplates.get(structureFile) != null
1432 && !phyre2ModelTemplates.get(structureFile).isEmpty();
1435 public String getPhyre2FastaFileFor(String structureFile)
1437 return phyre2ModelTemplates.get(structureFile);
1441 public static StructureSelectionManager getStructureSelectionManager()
1443 return instances.values().iterator().next();
1446 public void addStructureMapping(StructureMapping smapping)
1448 mappings.add(smapping);